1

I made a simple custom JsonConvert class. Right now I'm trying to convert the JSON data to a custom class like so:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    //JObject jo = JObject.Load(reader);
    MyItem instance = serializer.Deserialize<MyItem>(reader);

    // want to do more thing here...
}

Every time it executes the Deserialize<>() method it re-enters the ReadJson method and thus keeping me in a never ending loop.

How can I convert the JSON data to my custom object without ending up in a never ending loop?


Updated

The JSON I'm receiving is generic. I need the custom converter to map it to the right type. The JSON looks like this:

{
    /* Base obj properties, should be mapped to Page.cs */
    "$type": "App.Models.Page, App",
    "title": "Page title",
    "technicalName": "some_key",
    "fields": [

        /* Should be mapped to InputField.cs */
        {
            "$type": "App.Models.InputField, App",
            "type": "input",
            "typeTitle": "Input",
            "title": "Input",
            "technicalName": "input",
            "inputType": "text",
            "defaultValue": "Input default value"
        },

        /* Should be mapped to TextareaField.cs */
        {
            "$type": "App.Models.TextareaField, App",
            "type": "textarea",
            "typeTitle": "Textarea",
            "title": "Textarea",
            "technicalName": "textarea",
            "defaultValue": "default textarea value"
        }
    ]
}

In short my class files look like this:

class Page
{
    public string Title {get;set;}
    public string TechnicalName {get;set;}

    public List<Field> Fields {get;set;} // Note the base class "Field"
}

class InputField : Field // Field has base properties
{
 // InputField has its own properties
}

class TextareaField : Field // Field has base properties
{
 // TextareaField has its own properties
}

TypeNameHandling

I've set the json formatters settings:

jsonOutputFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
jsonInputFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;

When I output a Page object through Web API then I get a JSON structure exactly like the one above. When I sent back that exact JSON data I expect it to nicely map back to a Page object with the correct types in the Field list property.

But all the Fields are mapped to its base class Field instead of the types that are defined in $type.

So currently the JSON formatter works great for outputting. It shows all the $types. But the input mapping isn't really mapping back to its specific types.

13
  • Why did you create a custom JsonConvert in the first place? Why not use the one provided by the library? Commented May 25, 2015 at 11:45
  • @YuvalItzchakov Because I have a page that posts a JSON array which can be of a generic type. I'm eventually going to use the custom converter to map it back to the right type. Commented May 25, 2015 at 11:49
  • You can try changing the method signature to public new object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) Commented May 25, 2015 at 11:51
  • @JurgenCamilleri Doesn't work, it's an abstract method that needs to be overridden. Commented May 25, 2015 at 11:52
  • @Vivendi Post your JSON structure. Commented May 25, 2015 at 11:53

2 Answers 2

1

Given that you use Json.NET on the Web API side, you don't need a custom JsonConverter. You can explicitly tell the JsonFormatter (which internally uses Json.NET) to use TypeNameHandling.All. That way, it'll know exactly which type to deserialize given an IEnumerable<BaseType>. More on that can be find in how to deserialize JSON into IEnumerable<BaseType> with Newtonsoft JSON.NET

Sign up to request clarification or add additional context in comments.

Comments

1
public static class ConvertToJson
{ 
    public static T Deserialize<T>(string json)
    {
        using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            return (T)serializer.ReadObject(ms);
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.