我有以下JSON:
{
"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 :(得分:1)
执行此操作的一种方法是编写您自己的JsonConverter
(如图Here所示)并跟踪您的节点ID(例如,在Dictionnary
中)在反序列化过程中。然后,您可以在创建新Edges
时每次都检索相应的Node
。
因此,在您的自定义转换器中,您可以使用以下内容:
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
个循环但不同之处在于,唯一的搜索就是从字典中获取列表,而且我认为这是非常小的。我希望这有助于或至少为您提供另一种方式来看待它。
答案 1 :(得分:0)
我建议你为Edge写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)
并返回from节点。优点是您不需要将方法放在Node类中检索节点,也不需要从每个边缘保持与图形的父关系。