19

I want to force a Number to be a Float, after JSON.stringify(). Unfortunately JSON.stringify() deletes the 1 .0.

Example :

JSON.stringify(1.0) // "1"

Wanted outcome:

JSON.stringify(1.0) // "1.0"

I'm using an API which wants an object in JSON-Format, but it only understands decimal values. So I wanted to ask if it is possible using JSON.stringify to generate the string with decimal values without using Regex-.replace-magic

2
  • 2
    I'm guessing you want it to still output "1" for JSON.stringify(1) though? There's no such thing as a "float" in JavaScript, only Number. stringify has an overload which takes a function. Use that to determine what to output. Commented Dec 30, 2016 at 16:30
  • 1
    @MikeMcCaughan no JSON.stringify(1) should also output "1.0". Yes I've seen this overload function. The problem is; when I used JSON.stringify({Test:1}, function(key, value){ if(key == 'Test') { return value.toFixed(1) } return value; }); // "{"Test":"1.0"}". I dont want to have the quotation marks after "Test":**"** 1.0 "* Commented Dec 30, 2016 at 16:49

4 Answers 4

8

Use toFixed instead of stringify. Example:

var num = 1;
var numStr = num.toFixed(1); //result is "1.0"

More about toFixed - http://www.w3schools.com/jsref/jsref_tofixed.asp.

To be clear We are talking about conversion number to string not number to float ( such type not exists in javascript ) like can be understood from question description. toFixed will always return String with specified number of decimals.

Sign up to request clarification or add additional context in comments.

5 Comments

I would recommend using MDN for references (.toFixed()).
would result to to JSON.stringify(1.toFixed(1)) // '"1.0"'. Not what I'm searching for. It must'nt have quotation marks
@LivioBrunner way You are stringify String again? toFixed gives string so not need to use it inside stringify again.
@MaciejSikora unfortunately I must use JSON.stringify() :/
Problem is; I'm using an API which wants an object in JSON-Format, but it only understands decmiaml values. So I wanted to ask if it is possible using JSON.stringify to generate the string with decimal values without using Regex-.replace-magic
8

The straight and reasonably short answer to your question is no, you cannot customize the serialization of numeric values with JSON.stringify. See JSON.stringify() on MDN.

If you really need decimals for your integers you have to use "regex-magic" as you mention in your question or find a library allowing you to perform such tricks. If you aren't dealing with overly complex or many different kinds of objects you could probably stringify them manually.

As a sidenote, it sounds very, very suspicious with an API that needs to be fed with custom formatted JSON. I would tripple-check if there are any other way of using it.

1 Comment

Thanks for your answer. Well I'll figure something out. Unfortunately this will affect the cleanness of my code :( Well it is true, I must use double values, I triple checked it. I'm not directly using an API, but something equivalent. I want to create a library which generates "Minecraft Commands", and these commands dont get parsed well by Minecraft. If you want to know more about this issue, pm me, otherwise, have a nice day :)
5

Well for anyone wondering about the regex magic here it is: This is taken from stringify-with-floats npm library but modified to support any length of floats.

const beginFloat = "~begin~float~";
const endFloat = "~end~float~";

const stringifyWithFloats =
  (config = {}, decimals = 1) =>
  (inputValue, inputReplacer, space) => {
    const inputReplacerIsFunction = typeof inputReplacer === "function";
    let isFirstIteration = true;
    const jsonReplacer = (key, val) => {
      if (isFirstIteration) {
        isFirstIteration = false;
        return inputReplacerIsFunction ? inputReplacer(key, val) : val;
      }
      let value;
      if (inputReplacerIsFunction) {
        value = inputReplacer(key, val);
      } else if (Array.isArray(inputReplacer)) {
        // remove the property if it is not included in the inputReplacer array
        value = inputReplacer.indexOf(key) !== -1 ? val : undefined;
      } else {
        value = val;
      }
      const forceFloat =
        config[key] === "float" &&
        (value || value === 0) &&
        typeof value === "number" &&
        !value.toString().toLowerCase().includes("e");
      return forceFloat ? `${beginFloat}${value}${endFloat}` : value;
    };
    const json = JSON.stringify(inputValue, jsonReplacer, space);
    const regexReplacer = (match, num) => {
      return num.includes(".") || Number.isNaN(num)
        ? Number.isNaN(num)
          ? num
          : Number(num).toFixed(decimals)
        : `${num}.${"0".repeat(decimals)}`;
    };
    const re = new RegExp(`"${beginFloat}(.+?)${endFloat}"`, "g");
    return json.replace(re, regexReplacer);
  };

const test = {
  test: "test",
  float: 1.2,
  number: 1,
};

const formatted = stringifyWithFloats(
  { float: "float", number: "float" },
  2
)(test, null, 2); // null and 2 is just for pretty print

console.log(formatted);

Comments

2

Use JSON.rawJSON() prior to calling JSON.stringify() -- see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/rawJSON

Keep in mind that rawJSON doesn't work on Safari. Check 'Browser compatibility' section for more details

JSON.stringify will then print the plain string produced by toFixed without further formatting attempts. Ergo, the number translated into a string will be printed without quotes.

Example:

const myNumber = 1.0;
const result = JSON.stringify(JSON.rawJSON(myNumber.toFixed(1))); // 1.0
console.log("result: ", result);

1 Comment

Doesn't work on Safari as it doesn't support that API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.