skip to Main Content

What I need:

  • Deserialize Json string to and object
  • Do some stuff
  • return it as a string at the end

What is the problem?
When Json has property like {"foobar" : 0.0000000000000000001}, it is converted as a number, but then as a string it is represented in scientific notation as 1E-19

Is there a way to read number from json as a string, or convert such a number later to exact same string, without any precision loss? Precision is not fixed and number in json can occur in any property.
Usage of Newtonsoft is preferable (if it’s possible) over System.Text.Json

I’ve tried to

  1. create Newtonsoft’s CustomJsonConverter
  2. use System.Text.Json.JsonNumberHandling.WriteAsString
  3. converting float to string
    but any of this solutions didn’t work
  4. I couldn’t find a way to treat any number value as a string, idk if it’s even possible in such converter
  5. This one I think works only one way, from obj to string, and this is not what I’m looking for
  6. such a conversion didn’t work because it lost a precision, or did "over precision" (0.00…01 was written as 0.00…0989919999 or smth like this), or added additional zeros at the end – depends what formatting I’ve used

Ideally I’d like to convert string like {"foobar": 21.37} to object with property foobar = "21.37" to be sure that any precision won’t be lost after coverting between number/string

Minimal Reproducible Example

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

var json = """
    [{
        "foobar1": 21.37000,
        "foobar2": 0.0000000000000000001000,
        "foobar3": 1.1000E-19,
        "aReallyBigInteger" : 1111199999999999999999999999999999999911111
    }]
    """;
var input = JsonConvert.DeserializeObject<JToken>(json);

Console.WriteLine(input);
/*
Expected result:
[
  {
    "foobar1": "21.37000",
    "foobar2": "0.0000000000000000001000",
    "foobar3": "1.1000E-19",
    "aReallyBigInteger": "1111199999999999999999999999999999999911111"
  }
]
Current Behavior:
[
  {
    "foobar1": 21.37,
    "foobar2": 1E-19,
    "foobar3": 1.1E-19,
    "aReallyBigInteger": 1111199999999999999999999999999999999911111
  }
]
*/

2

Answers


  1. Chosen as BEST ANSWER

    MY SOLUTION

    Smelly code but the one that worked for me.

    1. deserialize json with System.Text.Json
    2. serialize it with use of custom converter written by Groxan here back to json
    3. New json can be deserialized using standard Newtonsoft and our numbers are already strings and are treated like ones.

    Probably terrible efficiency but only one that meets my requirements.


  2. I tried building a custom Converter class like the one shown below and used it to deserialize a JSON string containing numbers, and it seems to be returning the numbers as string without losing any precision. Please give it a try and let me know if it works.

    public class NumberToStringConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(decimal) || objectType == typeof(double) || objectType == typeof(float);
        }
        
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JToken token = JToken.Load(reader);
            if (token.Type == JTokenType.Float || token.Type == JTokenType.Integer)
            {
                return token.ToString();
            }
            throw new JsonSerializationException($"Unexpected token type: {token.Type}");
        }
        
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteValue(value.ToString());
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search