How to bind this property when deserializing a JSON object in C # Web Api?

I have a C # class that looks like

public class Node { public int Id { get; set; } /** Properties omitted for sake of brevity **/ public Node ParentNode { get; set; } } 

In the browser, I sent the JSON object as follows

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

If the value 1 assigned to the ParentNode property is the database identifier. So, in order to properly bind 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; } } 

Since I get "The current JsonReader is not an object: Integer. Path ParentNode", how can I adapt the ReadJson method to bind the ParentNode property or anything else that needs an individual conversion?

UPDATE

I saw JsonPropertyAttribute , in the API documentation of which

Instructs JsonSerializer to always serialize the member with the specified name

However, how can I instruct JsonSerializer programmatically - in my case, in the ReadJson method - to use this JsonPropertyAttribute?

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

+5
source share
2 answers

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

When calling serializer.Populate(jObject.CreateReader(), node); the serializer will fall into the ParentNode property of type Node , and then try to NodeJsonConverter it using NodeJsonConverter . At this point, the reader has moved and you no longer have StartObject , but you installed Integer . I think you can check the reader.TokenType property to find out if you are in the first call or subsequent call and process 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; } 
+2
source

You can create a public ParentNodeId and ParentNode with a private installer. Then you pass ParentNodeId where this installer will execute your code to populate the ParentNode. Now you can serialize your model to JSON and pass it to the client ... or what 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; } } 
0
source

All Articles