5

I have a c# class which looks like

public class Node {

    public int Id { get; set; }

    /** Properties omitted for sake of brevity **/

    public Node ParentNode { get; set; }

}

From a browser, I submitted a JSON object as follows

{"Id":1, "ParentNode":1}

Where the value 1 assigned to the ParentNode property representes a database identifier. So, in order to bind properly to my model, i need to write a custom JSON converter

public class NodeJsonConverter : JsonConverter
{

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return null;
        }

        /** Load JSON from stream **/
        JObject jObject = JObject.Load(reader);

        Node node = new Node();

        /** Populate object properties **/
        serializer.Populate(jObject.CreateReader(), node);

        return node;
    }
}

Because i get a "Current JsonReader item is not an object: Integer. Path ParentNode'", how can adapt the ReadJson method in order to bind the ParentNode property or anything else which needs custom conversion ?

UPDATE

I have seen JsonPropertyAttribute whose API documentation states

Instructs the JsonSerializer to always serialize the member with the specified name

However, how can i instruct programatically a JsonSerializer - in my case, in the ReadJson method - to use a given JsonPropertyAttribute ?

http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonPropertyAttribute.htm

1
  • 1) Do you need to serialize, or only deserialize? 2) Assuming you have read the parent node ID, how can you get the parent node to set it in the child? Commented May 12, 2015 at 19:09

2 Answers 2

2

I think the issue here is that the parsing becomes recursive due to a Node containing a Node in the form of the ParentNode property.

On the call to serializer.Populate(jObject.CreateReader(), node); the serializer will hit the ParentNode property which is of type Node and it will then attempt to parse that using your NodeJsonConverter. At that point the reader has moved on and you no longer have a StartObject but insted you have an Integer. I think you can check the reader.TokenType property to see if you are in the first call or the subsequent call and handle it accordingly:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.TokenType == JsonToken.Null)
    {
        return null;
    }

    Node node = new Node();

    if (reader.TokenType == JsonToken.StartObject)
    {
        //initial call
        //here we have the object so we can use Populate
        JObject jObject = JObject.Load(reader);
        serializer.Populate(jObject.CreateReader(), node);
    }
    else
    {
        //the subsequent call
        //here we just have the int which is the ParentNode from the request
        //we can assign that to the Id here as this node will be set as the 
        //ParentNode on the original node from the first call
        node.Id = (int)(long)reader.Value;
    }

    return node;
}
Sign up to request clarification or add additional context in comments.

Comments

0

You can make a public ParentNodeId and a ParentNode with private setter. Then you pass the ParentNodeId where that setter will do your code to populate the ParentNode. Now you can serialize your model to JSON and pass it back to the client... or what ever you want to do with it. SOmething like,

public class Node {

public int Id { get; set; }

/** Properties omitted for sake of brevity **/
private int _parentNodeId;
public int ParentNodeId { get {return _parentNodeId;}
set
{
    _parentNodeId = value;
    ParentNode = GetParentNodePropertyValues(_parentNodeId);
} 
}
public Node ParentNode { get; private set; }

}

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.