Json.NET Preserve double/decimal datatypes

I have reduced our real-world case to a simpler one (which may now look a bit constructed, yet hopefully easier to comprehend). Basically we have an loosely typed array object[] which may contain a mixture of decimal and double values as well as all kinds of other objects (strings, dates, other primitives, nested arrays, custom classes, etc). We want to use Json.NET for transferring such array to a remote machine, and we expect the original CLR datatypes of the numeric values to be preserved on the recipient end. The problem is that depending on the FloatParseHandling option, all numbers are either converted to double or to decimal after deserialization. Not very surprising knowing that the type information for primitives is not written by the serializer, but we don't mind adding this information to the output in any way (we need no interop, both ends are our own C# programs).

How would you recommend to configure the serializer to preserve the types of numeric values? Ideally (but not necessarily) we would want the smallest possible format like:

[
    "hello",
    1.0, // double
    2.0m, // decimal (preferable format, but unfortunately INVALID)
    { "$": "2.0m" }, // less readable, yet still compact enough
    { "type": "Decimal", "value": 2.0 }, // less pretty alternative, but would do as well...
    [
        // nested array or object
    ],
    // etc.
]

It seems to be relatively easy to implement a JsonConverter which writes such content, but we are stuck at implementing the ReadJson overload which only applies custom logic to tokens with 'm' suffix and falls back to the default implementation for anything else.

EDIT 1: marked my "preferable format" as INVALID, added a shorter valid alternative, yet the original question - how to implement it in Json.NET - remains open.

Jon Skeet
people
quotationmark

Your preferred format simply isn't JSON. Values in JSON are only:

  • Numbers (no differentiation between integers and non-integers)
  • Strings
  • Objects
  • Arrays
  • Boolean true/false
  • null

That's it.

So the only way of preserving extra information reliably without breaking JSON would be to serialize the values as objects with the type information, as per your

{ "type": "Decimal", "value": 2.0 }

example... although in that case I'd make the value a string as otherwise you could very easily lose information. (Not every System.Decimal is exactly representable as a System.Double or vice versa.)

people

See more on this question at Stackoverflow