Bunny83 / SimpleJSON

A simple JSON parser in C#
MIT License
735 stars 294 forks source link

Suggestion to replace "," for . in double/float type #46

Closed TheFonsi closed 2 years ago

TheFonsi commented 3 years ago

I suggest replace ',' for '.' in double/float type. In JSON we can use '.' without quote. There will be lighter files.

1: { "txt": "mod1", 1: { "timeline": 12.3, //now we must use "timeline": "12,3",

Bunny83 commented 3 years ago

I think I do not really understand what you're asking here. The JSON format is pretty well defined. So I don't really understand your suggestion or what to replace where. The sample you provided is not valid json but not because of commas or dots. Json only accepts a dot as decimal point. I myself live in germany where we use a comma as decimal point, however the Json format is a well defined culture independent format and always uses the dot as decimal point.

Note that a 1 is not a valid key in pure json either. My parser may accept it because it is quite fault tolderant. However using 1 without quotes as a key is wong and would not be accepted by most parsers or validators.

Note that while JSON stands for JavaScript Object Notation, JSON itself is its own subset of the javascript language and is more restrictive. In JSON only double quotes are allowed. As I said, the format is very well defined, so I don't really understand your suggestion or what exactly you want to have changed. I think you have to be way more specific with your description :)

TheFonsi commented 3 years ago

Of course I understand. But I ran into a problem where the parser could not handle the value, e.g. value: 16.3 everywhere after reading was 0, but only after converting: 16.3 to: "16.3" will correctly read 16.3

Bunny83 commented 3 years ago

That's unlikely. Do you have an example json text that will reproduce this issue? Have you checked your original json text in a validator that it's actually valid json? What you just said in yout last comment doesn't seem to have anything do do with a comma, or does it? If not your title is even more confusing.

TheFonsi commented 3 years ago

Ye I checked the JSON file in validator with RFC4627.

{
  "1": {
    "modName": "fs1",
    "1": {
      "timeline": 10,
      "text": "Example text",
      "nextSceneTime": 16.3
    }
  }
}

In Debug.Log(); I get properly 16.3 but when I assigned it to the variable of type double this variable return me in Debug.Log() value 0

double timeline;
var N = JSON.Parse(jsonFile.ToString());
Debug.Log(N["1"]["1"]["nextSceneTime"]); //Return 16.3
timeline = N["1"]["1"]["nextSceneTime"]; //Adding .AsDouble don't resolve this problem.
Debug.Log(timeline); //Return 0, but when in json file i will change 16.3 to "16,3" it work correctly and return 16.3 in variable double.
Bunny83 commented 3 years ago

I copied your code as it is in my test project and both print 16.3 as expected. Are you sure you use the latest version of SimpleJSON here?

The you may get a value of 0 when the key you try to access does not exist. The double conversion operator does check for null and if the value is null / does not exist it will simply return 0. However when the key / value exists it is returned correctly. I asked for some code that reproduces the error. Did you actually run that code you posted here? If it works for you as well but you have issues in your production code, the error has to be something else. Keep in mind that you can always use .ToString(3) to convert any JSONNode back to json. This might help to figure out at which point your code went wrong.

TheFonsi commented 3 years ago

This problem occurs in this parts of project. If needed: Unity Version: 2019.2.18f1

{
  "1": {
    "moduleName": "comtext",
    "1": {
      "timeline": 44,
      "isUnique": true,
      "text": "comtext",
      "answers": {
        "1": {
          "text": "comtext",
          "points": 0,
          "timelineInSecAfterAnswer": 45,
          "playNextAfter": -1
        },
        "2": {
          "text": "comtext",
          "points": 5,
          "timelineInSecAfterAnswer": 45,
          "playNextAfter": -1
        },
        "3": {
          "text": "comtext",
          "points": 10,
          "timelineInSecAfterAnswer": 45,
          "playNextAfter": -1
        }
      },
      "nextSc": -1
    },
    "2": {
      "timeline": 63,
      "isUnique": true,
      "text": "comtext",
      "answers": {
        "1": {
          "text": "comtext",
          "points": 0,
          "timelineInSecAfterAnswer": 64,
          "playNextAfter": -1
        },
        "2": {
          "text": "comtext",
          "points": 5,
          "timelineInSecAfterAnswer": "96,3",
          "playNextAfter": -1
        },
        "3": {
          "text": "comtext",
          "points": 10,
          "timelineInSecAfterAnswer": 124.3,
          "playNextAfter": -1
        }
      },
      "nextSc": -1
    }
  }
}

image

And part of code:

timelineInSecAfterAnswer = N[Convert.ToString(scenarioID)][Convert.ToString(interactionID)]["answers"][Convert.ToString(answerID)]["timelineInSecAfterAnswer"];
                    Debug.Log("S: "+ N[Convert.ToString(scenarioID)][Convert.ToString(interactionID)]["answers"][Convert.ToString(answerID)]["timelineInSecAfterAnswer"]);
                    Debug.Log("L: "+timelineInSecAfterAnswer);
Bunny83 commented 3 years ago

I just tested with your provided data and I get the expected output of SimpleJSONResult

I used this code as I don't know where your parameters come from:

        foreach (var kv in N["1"]["2"]["answers"])
        {
            double timelineInSecAfterAnswer = kv.Value["timelineInSecAfterAnswer"];
            Debug.Log("S: " + kv.Value["timelineInSecAfterAnswer"]);
            Debug.Log("L: " + timelineInSecAfterAnswer);
        }

I simply used a foreach loop to iterate over the answers. However I access the actual "timelineInSecAfterAnswer" value the same way you did. As expected I correctly get the 124.3 but obviously the "96,3" can not be converted into a double as it's not a valid double value. I still can not reproduce your issue with your data and your code.

ps: Note: as you can see in the screenshot, the last "L" log line contains a "comma" because the default double to string conversion uses the local culture setting and as I said previously where in germany we use the comma as decimal point. So everything does exactly work as expected.

TheFonsi commented 3 years ago

So my problem is related to local culture setting and there's nothing you can do about it? It is not impossible to add support to both: , and . ?

Bunny83 commented 3 years ago

Possible? sure, but numbers with comma as decimal point does not follow the JSON format standard and would not be valid json. When the number is stored as a string you can always parse it manually any way you like. That's why the SimplyJSON uses the invariant culture to parse the numbers because that's how the it has to look like.

A similar thing is true for values that can not be represented as a double. The json format allows arbitrarily precice numbers, however the standard also suggests that you should not assume support for something higher than what a double can represent. When in doubt it's recommended to put your data into a string instead so the application can parse / encode it however it likes. For example long values are too large to be represented as a double (at least long values close to its max range). So in order to handle long values properly, they are serialized as strings in order to be consistent with the format standard.