2017-06-21 37 views
1

对象,我有以下JSON:反序列化JSON与儿童通过ID

{ 
    "graph": { 
     "edges": [{ 
      "fromNode": "1", 
      "toNode": "2", 
      "distance": 200 
     }], 
     "nodes": [{ 
      "id": "1", 
      "lat": 10.402875, 
      "lng": 53.611151 
     }] 
    } 
} 

对于反序列化我有这个类:

public class Graph { 

    public Node [] nodes { get; set; } 
    public Edge [] edges { get; set; } 
} 

public class Node { 

    public string id { get; set; } 
    public double lat { get; set; } 
    public double lng { get; set; } 
} 

public class Edge { 

    public string fromNode { get; set; } 
    public string toNode { get; set; } 
    public int distance { get; set; } 
} 

当我想反序列化JSON我调用这个函数:

JsonConvert.DeserializeObject<Graph> (content); 

现在我想通过反序列化来获得边缘类中的引用节点对象,如下所示:

public class Edge { 

    public Node fromNode { get; set; } 
    public Node toNode { get; set; } 
    public int distance { get; set; } 
} 

在反序列化之后没有foreach循环的例子吗?

+0

您可以先修改JSon和解析节点吗? – Mat

+1

这是不可能通过简单的反序列化。一旦你使用反序列化获得图形对象,你需要编写逻辑来获取节点和节点对象,编号为 –

+0

有没有一个可选逻辑的例子来通过编号获取对象? – Maxim

回答

0

我建议你写extension methods的边缘返回节点:

public static class ExtensionMethods 
    { 
     public static Node FromNode(this Edge edge, Graph graph){ 
      return graph.Nodes.FirstOrDefault(n => n.id.Equals(edge.fromNode); 
     } 

     public static Node ToNode(this Edge edge, Graph graph){ 
      return graph.Nodes.FirstOrDefault(n => n.id.Equals(edge.toNode); 
     } 
    } 

之后,你可以调用edge.FromNode(graph)和节点得到回来。好处是您不需要将方法放在Node类中检索节点,也不需要在每条边上保持父图关系。

1

一种方法是编写自己的JsonConverter(如图所示Here),并在反序列化过程中跟踪您的节点ID(例如,在Dictionnary中)。然后,您可以每次创建新的Node时简单检索相应的Edges

因此,在您自定义转换你有这样的事情:

public override object ReadJson(JsonReader reader, Type objectType 
     , object existingValue, JsonSerializer serializer) 
{ 

    Graph graph = new Graph(); 
    List<Edge> graphEdges = new List<Edge>(); 
    List<Node> graphNodes = new List<Node>(); 

    Dictionnary<int, List<Edge>> fromNodesMap = new Dictionnary<int, List<Edge>>(); 
    Dictionnary<int, List<Edge>> toNodesMap = new Dictionnary<int, List<Edge>>(); 

    /* Parse the 'edges' array, I'm omitting the reading stuff here */ 

    var edge = new Edge(); 

    int fromNode = Convert.ToInt32(((JValue)obj["fromNode"]).Value); 
    if (fromNodesMap.Contains(fromNode)) { 
     fromNodesMap[fromNode].Add(edge); 
    } else { 
     var edgeList = new List<Edge>(); 
     edgeList.Add(edge); 
     fromNodesMap.Add(fromNode, edgeList); 
    } 

    int toNode = Convert.ToInt32(((JValue)obj["toNode"]).Value); 
    if (toNodesMap.Contains(toNode)) { 
     toNodesMap[toNode].Add(edge); 
    } else { 
     var edgeList = new List<Edge>(); 
     edgeList.Add(edge); 
     toNodesMap.Add(toNode, edgeList); 
    } 

    edge.distance = Convert.ToInt32(((JValue)obj["distance"]).Value); 

    graphEdges.Add(edge); 

    /* Parse the 'nodes' array, I'm omitting the reading stuff here */ 

    var node = new Node(); 
    int nodeId = Convert.ToInt32(((JValue)obj["id"]).Value); 
    node.lat = Convert.ToDouble(((JValue)obj["lat"]).Value); 
    node.lng = Convert.ToDouble(((JValue)obj["lng"]).Value); 

    var listEdgesSameFrom = fromNodesMap[nodeId]; 
    foreach (var edge in listEdgesSameFrom) 
     edge.fromNode = node; 

    var listEdgesSameTo = toNodesMap[nodeId]; 
    foreach (var edge in listEdgesSameTo) 
     edge.toNode = node; 

    graphNodes.Add(node); 

    /* Read till end */ 

    graph.edges = graphEdges.ToArray(); 
    graph.nodes = graphNodes.ToArray(); 

    return graph; 
} 

免责声明我没有测试过,但逻辑是存在的。

现在我知道在那里有foreach循环,但区别在于唯一的搜索就是从字典中获取列表,而且我认为这很简单。我希望这有助于或至少给你另一种方式来看待它。