6

I have a string like this:

var str = "{'data': {'someProperty': 0.00001}}";

When I parse it to JObject like that

var jObject = JObject.Parse(str);

My jObject looks like this:

{"data": {"someProperty": 1E-05}}

I need to get rid of scientific notation so that resulting JObject would look like original json.

I managed to do that using later version of Newtonsoft.Json like that:

var serializer = new JsonSerializer { FloatParseHandling = FloatParseHandling.Decimal };
using (System.IO.TextReader tr = new System.IO.StringReader(str)
using (var jsonReader = new JsonTextReader(tr))
{
    var jp = serializer.Deserialize(jsonReader);
    var jObject = JObject.FromObject(jp);
}

But I need to achieve the same result using Newtonsoft.Json version 3.5 which does not have a FloatParseHandling property. I guess I need to implement a JsonConverter somehow, but I have no idea how to do that, since my real json is much more complex than the one in example and I need to handle all the float values in it the right way.

So, what would be the right way to get a JObject without a scientific notation for float values using Newtonsoft 3.5?

  • String and property wrapper with parsing. – DrkDeveloper Dec 06 '19 at 17:00
  • Possible duplicate of: https://stackoverflow.com/questions/1546113/double-to-string-conversion-without-scientific-notation – Casey Crookston Dec 06 '19 at 17:07
  • you can cast the value to decimal, which will return the correct value, and use `ToString()` if you need to work on string values. example `var someProperty = ((decimal) jObject["data"]["someProperty"]).ToString();` – iSR5 Dec 06 '19 at 17:25

4 Answers4

3

Following produces the object you are looking for

JObject.Load(new JsonTextReader(new StringReader(str)) { FloatParseHandling = FloatParseHandling.Decimal }, null)

taken from here:

EDIT: JTokenTypes in NewtonSoft v 3.5.8 are limited to Float and Integer (in regards to decimal). There is no decimal type in that version and thus makes it not possilbe to have a decimal value in that JObject.

JTokenTypes from v3 of newtonsoft

    None = 0,
    Object = 1,
    Array = 2,
    Constructor = 3,
    Property = 4,
    Comment = 5,
    Integer = 6,
    Float = 7,
    String = 8,
    Boolean = 9,
    Null = 10,
    Undefined = 11,
    Date = 12,
    Raw = 13,
    Bytes = 14

The right way to do this would be to upgrade the Newtonsoft package :)

Jawad
  • 11,028
  • 3
  • 24
  • 37
  • Thank you. But I indicated that I cannot use FloatParseHandling. – Илья Иваницкий Dec 06 '19 at 17:27
  • This is good for deserializing json which only have a property of type float or a string representation of float number. My json is complex with nested objects, properties of different types and arrays. I need it to be deserialized just like JObject.Parse() do, but just the numbers to be deserialized without a scientific notation – Илья Иваницкий Dec 06 '19 at 17:53
  • @ИльяИваницкий see my EDIT. – Jawad Dec 06 '19 at 19:07
  • 1
    This would be a good time to formally propose to your leadership that you update versions. It should be pretty easy to show that it would make more business sense to upgrade versions numbers than to have one of their devs spending hours or even days on something the tool they are already using can do off the shelf if they would only keep up with upgrades. –  Dec 06 '19 at 19:17
  • @ИльяИваницкий does this answer your question – Jawad Dec 13 '19 at 14:52
  • Well, I guess there is no better option than updating the version. So I will mark this answer. Thanks everyone. – Илья Иваницкий Dec 17 '19 at 11:06
1

Jawad's provided code is not the best solution because it will end up in memory leaks. StringReader and JsonTextReader are both implementing the IDisposable interface and therefore must be disposed if they are not used anmyore. Safer code would be:

public JObject CustomJObjectLoad(string str)
{
    using (var stringReader = new StringReader(str))
    {
        using (var jsonReader = new JsonTextReader(stringReader) { FloatParseHandling = FloatParseHandling.Decimal })
        {
            return JObject.Load(jsonReader, null);
        }
    }
}
DerAlex23
  • 31
  • 1
  • 5
0

First, your json isn't valid :) It should have double quotes:

{"data": {"someProperty": 0.00001}}

But even better, using standard casing, would be:

{"Data": {"SomeProperty": 0.00001}}

And then, we can do this:

var str = "{\"Data\": {\"SomeProperty\": 0.00001}}";
dynamic myObject = JsonConvert.DeserializeObject(str);
var val = myObject.Data.SomeProperty.ToString("0." + new string('#', 339));

val will then be: "0.00001"

(Note: I stole the solution from: Double to string conversion without scientific notation)

Casey Crookston
  • 13,016
  • 24
  • 107
  • 193
  • Thanks, but I would like to avoid creating classes if possible, since I cannot guarantee the exact shape of json. – Илья Иваницкий Dec 06 '19 at 17:31
  • I have a complex json with many properties, nested objects, arrays etc. SomeProperty is just for example. I need all float values to be handled correctly. – Илья Иваницкий Dec 06 '19 at 17:47
  • Ok, I read the edits to your OP. I understand better now what you are trying to do. You want to change the way doubles are serialized. But, may I ask why? For any math purposes, the scientific notation will still work just fine. I assume you only want to change it for display purposes, right? And if that's the case, why not just do the conversion right before doing the display? – Casey Crookston Dec 06 '19 at 18:34
  • The usage is not in my competence. I need to provide json for a third party and that is their requirement. – Илья Иваницкий Dec 06 '19 at 19:05
0

You can also create simple POCO object. and make sure someProperty is of type string and then de-serialize the json string

var myObject = Newtonsoft.Json.JsonConvert.DeserializeObject<YourObject>(json)
LP13
  • 30,567
  • 53
  • 217
  • 400