Search code examples
c#.netjson.net

How to deserialize raw json field to model using Newtonsoft?


So my json data is coming as string like following:

    { "name":"aaa", "sub": "{"x":"sss", "y":"eee"}" }
    

Sub field is a raw json string here.

My model is like following.

    class Main
    {
        public string Name { get;set;}
        public Sub Sub { get;set;}
    }

    class Sub
    {
        public string X { get;set;}
        public string Y { get;set;}
    }

I want to deserialize it like following:

var response = Encoding.UTF8.GetString(bytes); // getting data.
var jsonString = JsonConvert.Deseialize(response).ToString(); // to string.
var model = JsonConvert.Deserialize<Main>(jsonString); // error

The last step throws exception, like "string can not cast to Main" class.


Solution

  • Assuming your question has a typo and you meant to escape the double quotes, e.g.:

    { "name":"aaa", "sub": "{\"x\":\"sss\", \"y\":\"eee\"}" }
    

    Then you can achieve this with a custom converter. For example:

    public class NestedJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) => true;
    
        public override object? ReadJson(JsonReader reader, Type objectType, 
            object? existingValue, JsonSerializer serializer)
        {
            // Get the raw string
            var s = serializer.Deserialize<string>(reader);
    
            // Deserialise into the correct type
            return JsonConvert.DeserializeObject(s, objectType);
        }
    
        public override void WriteJson(JsonWriter writer, object? value, 
            JsonSerializer serializer)
                => throw new NotImplementedException();
    }
    

    And change your model to add the attribute:

    class Main
    {
        public string Name { get; set; }
        
        [JsonConverter(typeof(NestedJsonConverter))]
        public Sub Sub { get; set; }
    }
    

    Now you can simply deserialise like this:

    var result = JsonConvert.DeserializeObject<Main>(jsonString);