1

I'm working on a legacy system that works with IotHub SDK. The application uses both System.Text.Json (there's an agreement to use this for current & future development) and Newtonsoft.Json for (de)serializing JSON.

I need to deserialize the following JSON into a Dictionary<string,object> because the value can either be a string or a JSON object:

{
  "route1": "route 1 text",
  "route2": {
    "route": "route 2 text",
    "priority": 1,
    "timeToLiveSecs": 60
  }
}

What I expect is that the value would be deserialized as:

  • route1 as string
  • route2 as object

But System.Text.Json deserializes both values as JsonElement. And to get the value, a method like GetString() needs to be called (see last row) enter image description here

Because of the usage combination of Newtonsoft & System.Text.Json in this legacy application, serializing this object with Newtonsoft doesn't work.

enter image description here

The deserialization & re-serialization only works when the same libraries were used in both process. And IoTHub SDK from Microsoft itself, uses Newtonsoft.Json.

Is there a way to make both libraries work together in this case? I find it dangerous to use either one to deserialize an object type with this behavior, when there's a chance 3rd party libraries may use another library.

adelb
  • 791
  • 7
  • 26
  • You could deserialize to a `Dictionary` and use `ObjectAsPrimitiveConverter` from [this answer](https://stackoverflow.com/a/65974452/3744182) to [C# - Deserializing nested json to nested Dictionary](https://stackoverflow.com/q/65972825/3744182). The converter will recursively deserialize arbitrary JSON to .NET foundational types such as `Dictionary`, `List` or primitives such as `string` and `double`, all of which are compatible with Json.NET. Does that answer your question? – dbc Jan 18 '23 at 18:04

1 Answers1

1

As taken from the official docs: "System.Text.Json is strict by default and avoids any guessing or interpretation on the caller's behalf, emphasizing deterministic behavior. The library is intentionally designed this way for performance and security. Newtonsoft.Json is flexible by default. This fundamental difference in design is behind many of the following specific differences in default behavior." Source: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/migrate-from-newtonsoft?pivots=dotnet-7-0

The core principle between Newtonsoft and the Microsoft differs as you can see. Also stated in the docs: "JsonElement is what you can search and enumerate over, and you can use JsonElement to materialize JSON elements into .NET types."

As seen in your screenshot, System.Text.Json detects the right type (string) -> see the ValueKind property. You can access the property and do your handling. Other than that, no there is no way to use both libs interchangeably since they have a different approach.

withJsonDeserializer["route1"].ValueKind
Aaron
  • 1,600
  • 1
  • 8
  • 14