0

I need to store an unknown JSON structure from an external API, but when I serialize the data using System.Text.Json, the JSON output is incorrect. A working example can be found here: https://dotnetfiddle.net/k0zBAs

Example data from external API:

[{"name":"source","choices":["Email","Portal","Phone","Forum"]}]

Output from System.Text.Json.Serialize

[{"name":"source","choices":[[],[],[],[]]}]

Why doesn't this serialize properly?

Initially, I deserialize the data from the external API to a class similar to the one below using the Newtonsoft library because it does a better job of deserializing the data than System.Text.Json. Interestingly, Newtonsoft will correctly serialize the data.

public class TestClass
{
    [Newtonsoft.Json.JsonProperty("name"), System.Text.Json.Serialization.JsonPropertyName("name")]
    public string Name { get; set; }

    [Newtonsoft.Json.JsonProperty("choices"), System.Text.Json.Serialization.JsonPropertyName("choices")]
    public object Choices { get; set; }
}

The Choices data I receive could be any type but I have noticed they are commonly one of these:

  • Dictionary<string, string[]>
  • string[]
  • Dictionary<string, int>
  • Dictionary<string, long>

I have a feeling it is something to do with this Microsoft article on migrating from Newtonsoft.Json, but I don't fully understand it.

oli_taz
  • 197
  • 1
  • 4
  • 18
  • Your problem is that you are trying to serialize a Newtonsoft `JToken` with `System.Text.Json`, which is not supported. You could use the same serializer for deserialization and subsequent serialization, or use the converter from [this answer](https://stackoverflow.com/a/65386084/3744182) to [How can I serialize a Newtonsoft JToken to JSON using System.Text.Json?](https://stackoverflow.com/q/65386083/3744182). In fact this might be a duplicate, agree? – dbc Jan 12 '21 at 18:21
  • Yeah that converter works, see https://dotnetfiddle.net/TBecoo. Still, mising `JToken` and `System.Text.Json` seems like a bad idea in the long run. It might be better to convert the `JToken` to a native .Net object along the lines of [How do I use JSON.NET to deserialize into nested/recursive Dictionary and List?](https://stackoverflow.com/q/5546142/3744182). – dbc Jan 12 '21 at 18:37
  • hanks for that link.. I agree that it is a similar question, however I forgot to mention that the data is stored as a string in a database between serialization/deserialization so `Choices` property would be treated as plain object when serializing back to `TestClass`. – oli_taz Jan 12 '21 at 19:02
  • So is your real requirement that to have a property `public string Choices` that is serialized and deserialized as "raw" json by both Newtonsoft and System.Text.Json? Can you please [edit] your question to include a [mcve] showing your precise requirements? – dbc Jan 12 '21 at 19:04
  • We are using an Entity Framework `ValueConverter` so that the object is converted to a JSON string using `System.Text.Json.Serialize` before being stored in the database. My [example](https://dotnetfiddle.net/k0zBAs) also serializes/deserializes using just the `System.Text.Json` library which produces the same results. My requirement is that `Choices` is correctly serialized to a JSON string like `Newtonsoft` handles it. From your answers I believe this can be done with custom `JsonConverter`. – oli_taz Jan 12 '21 at 19:28
  • 1
    Yes, the `JTokenConverterFactory` from the linked answer will correctly serialize any `JToken` subclass (other than `JConstructor` which is not part of the JSON standard) to `System.Text.Json`. – dbc Jan 12 '21 at 19:30

0 Answers0