2015-05-12 4 views
5

mam C# klasy, która wygląda jakJak powiązać daną właściwość przy deserializacji obiektu JSON w C# Web Api?

public class Node { 

    public int Id { get; set; } 

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

    public Node ParentNode { get; set; } 

} 

Od przeglądarce, złożyłam obiekt JSON następująco

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

Jeżeli wartość 1 przypisana do właściwości parentNode representes identyfikator bazy danych. Tak więc, w celu prawidłowego związania do mojego modelu, muszę napisać niestandardowej Converter 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; 
    } 
} 

bo dostać „pozycja Aktualny JsonReader nie jest obiektem. Integer Ścieżka parentNode '”, w jaki sposób można dostosować Metoda ReadJson w celu powiązania właściwości ParentNode lub czegokolwiek, co wymaga niestandardowej konwersji?

UPDATE

Widziałem JsonPropertyAttribute którego dokumentację API stwierdza

Nakazuje JsonSerializer zawsze serializacji elementu o podanej nazwie

Jednak, jak mogę polecić programowo a JsonSerializer - w moim przypadku, w metodzie ReadJson - użycie danego Jso nPropertyAttribute?

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

+0

1) Czy trzeba serializacji lub tylko deserializowania? 2) Zakładając, że odczytałeś identyfikator węzła nadrzędnego, w jaki sposób można uzyskać węzeł nadrzędny, aby ustawić go w podrzędnym? – dbc

Odpowiedz

2

Myślę, że problemem jest to, że podczas analizy staje rekurencyjny powodu Node zawierający Node w postaci nieruchomości ParentNode.

Na wezwanie do serializer.Populate(jObject.CreateReader(), node); serializer trafi na własność ParentNode który jest typu Node a zostanie on próbować analizować że używając NodeJsonConverter. W tym momencie czytnik przeniósł się i nie masz już StartObject, ale masz już Integer. Myślę, że można sprawdzić właściwość reader.TokenType aby sprawdzić, czy jesteś w pierwszej rozmowy lub późniejszej rozmowy i obsługiwać go odpowiednio:

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

Dziękuję bardzo! Uratowałeś mi dzień. –

+0

Nie ma za co, cieszę się, że mogłem pomóc. – petelids

0

Można zrobić ParentNodeId publicznego i prywatnego z parentNode seter. Następnie przekazujesz ParentNodeId, gdzie ten program ustawia kod w celu zapełnienia węzła ParentNode. Teraz możesz serializować model do JSON i przekazać go klientowi ... lub co chcesz z nim zrobić. Coś podobnego,

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

}