2015-05-12 5 views
5

У меня есть C# класс, который выглядит какКак связать заданное свойство при десериализации объекта JSON в C# Web Api?

public class Node { 

    public int Id { get; set; } 

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

    public Node ParentNode { get; set; } 

} 

Из браузера, я представил объект JSON следующим

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

Если значение 1 присваивается свойству ParentNode representes идентификатор базы данных. Итак, для того, чтобы правильно привязать к моей модели, я должен написать собственный JSON преобразователь

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; 
    } 
} 

Потому что я получаю "Текущий JsonReader пункт не является объектом:. Integer Path ParentNode", как можно адаптировать Метод ReadJson для привязки свойства ParentNode или чего-либо еще, для которого требуется индивидуальное преобразование?

UPDATE

Я видел JsonPropertyAttribute чьи API документации говорится

Инструктирует JsonSerializer всегда сериализовать элемент с указанным именем

Однако, как я могу поручить программно JsonSerializer - в моем случае, в методе ReadJson - использовать данный Jso nPropertyAttribute?

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

+0

1) вам нужно сериализовать, или только десериализации ли? 2) Предполагая, что вы прочитали идентификатор родительского узла, как вы можете заставить родительский узел установить его в дочернем? – dbc

ответ

2

Я думаю, что проблема здесь в том, что синтаксический анализ становится рекурсивным из-за Node содержащим Node в виде ParentNode собственности.

На призыв serializer.Populate(jObject.CreateReader(), node); сериализатор поразит ParentNode свойство, которое имеет тип Node и будет пытаться разобрать, что с помощью NodeJsonConverter. В этот момент читатель перешел, и у вас больше нет StartObject, но у вас есть Integer. Я думаю, вы можете проверить reader.TokenType свойство, чтобы увидеть, если вы находитесь в первом вызове или последующий вызов и обработать его соответствующим образом:

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; 
} 
+0

Большое вам спасибо! Ты спас свой день. –

+0

Добро пожаловать, рад, что смогу помочь. – petelids

0

Вы можете сделать публичное ParentNodeId и ParentNode с частным сеттера. Затем вы передаете ParentNodeId, где этот установщик выполнит ваш код, чтобы заполнить ParentNode. Теперь вы можете сериализовать свою модель на JSON и передать ее клиенту ... или что вы хотите с ней делать. Что-то вроде

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; } 

} 
Смежные вопросы