反序列化未知维度的锯齿状数组
Deserialize jagged array with unknown dimensions
我目前正在尝试使用 Json.NET 在 Unity 中解析一个 Json 文件,目前可以解析 80% 的数据。我遇到过这样格式的部分。
{
"features": [
{
"coordinates": [
[
[ 1, 1 ],
[ 2, 2 ]
]
]
},
{
"coordinates": [
[ 1, 1 ],
[ 2, 2 ],
[ 3, 3 ]
]
},
{
"coordinates": [
[
[ 1, 2 ],
[ 1, 2 ]
]
]
},
{
"coordinates": [
[
[
[ 1, 2 ],
[ 1, 2 ]
]
]
]
}
]
}
坐标数组可能包含未知数量的坐标,它也将是一个未知维度的锯齿状数组。我无法解析它,因为我不太精通 Json 反序列化。
感谢任何有关如何解决此问题的帮助。
我不确定你的数据有多少变化,但这里有一个使用递归的粗略想法。
void ParseCoordinateJSON()
{
var coordinates = new List<int[]>();
var parsed = JObject.Parse(rawJson);
var featureArray = parsed.SelectToken("features");
var coordArray = featureArray.Children();
coordArray.ToList().ForEach(n => ExtractCoordinates(n.SelectToken("coordinates"), coordinates));
Debug.Log(string.Join("\n", coordinates.Select(c => $"({string.Join(", ", c)})")));
}
void ExtractCoordinates(JToken node, List<int[]> coordinates)
{
if (node == null)
{
return;
}
if (node.Children().Any(n => n.Type == JTokenType.Integer))
{
coordinates.Add(node.Children().Select(n => n.Value<int>()).ToArray());
return;
}
node.Children().Where(n => n.Type == JTokenType.Array).ToList().ForEach(n => ExtractCoordinates(n, coordinates));
}
编辑:
这是没有 linq 的,可能更容易理解:
void ParseCoordinateJSONNoLinq()
{
var coordinates = new List<int[]>();
var parsed = JObject.Parse(rawJSON);
var featureArray = parsed.SelectToken("features");
// These will be the objects with a "coordinates" key and an array value.
var coordArray = featureArray.Children();
foreach(var node in coordArray)
{
ExtractCoordinatesNoLinq(node.SelectToken("coordinates"), coordinates);
}
Console.WriteLine(string.Join("\n", coordinates.Select(c => $"({string.Join(", ", c)})")));
}
void ExtractCoordinatesNoLinq(JToken node, List<int[]> coordinates)
{
var intValues = new List<int>();
// Step through each child of this node and do something based on its node type.
foreach(var child in node.Children())
{
// If the child is an array, call this method recursively.
if (child.Type == JTokenType.Array)
{
// Changes to the coordinates list in the recursive call will persist.
ExtractCoordinatesNoLinq(child, coordinates);
// The child type is an integer, add it to the int values.
} else if (child.Type == JTokenType.Integer)
{
intValues.Add(child.Value<int>());
}
}
// Since we found int values at this level, add them to the shared coordinates list.
if (intValues.Count > 0)
{
coordinates.Add(intValues.ToArray());
}
}
如果您的其余数据是可靠的,我会使用典型的数据对象并对它们进行反序列化,然后添加类似上面的内容作为表示锯齿状数组的对象的 Custom JSON Converter。
public class MyDataObject {
public string SomeField {get; set;}
public Vector2 Position {get; set;}
[JsonProperty("features")]
public JaggedFeatures {get; set;}
}
public class JaggedFeatures {
public List<int[]> Coordinates {get; set;}
}
//...
JsonConvert.Deserialize<MyDataObject>(rawJSON, new JaggedFeaturesConverter())
我目前正在尝试使用 Json.NET 在 Unity 中解析一个 Json 文件,目前可以解析 80% 的数据。我遇到过这样格式的部分。
{
"features": [
{
"coordinates": [
[
[ 1, 1 ],
[ 2, 2 ]
]
]
},
{
"coordinates": [
[ 1, 1 ],
[ 2, 2 ],
[ 3, 3 ]
]
},
{
"coordinates": [
[
[ 1, 2 ],
[ 1, 2 ]
]
]
},
{
"coordinates": [
[
[
[ 1, 2 ],
[ 1, 2 ]
]
]
]
}
]
}
坐标数组可能包含未知数量的坐标,它也将是一个未知维度的锯齿状数组。我无法解析它,因为我不太精通 Json 反序列化。
感谢任何有关如何解决此问题的帮助。
我不确定你的数据有多少变化,但这里有一个使用递归的粗略想法。
void ParseCoordinateJSON()
{
var coordinates = new List<int[]>();
var parsed = JObject.Parse(rawJson);
var featureArray = parsed.SelectToken("features");
var coordArray = featureArray.Children();
coordArray.ToList().ForEach(n => ExtractCoordinates(n.SelectToken("coordinates"), coordinates));
Debug.Log(string.Join("\n", coordinates.Select(c => $"({string.Join(", ", c)})")));
}
void ExtractCoordinates(JToken node, List<int[]> coordinates)
{
if (node == null)
{
return;
}
if (node.Children().Any(n => n.Type == JTokenType.Integer))
{
coordinates.Add(node.Children().Select(n => n.Value<int>()).ToArray());
return;
}
node.Children().Where(n => n.Type == JTokenType.Array).ToList().ForEach(n => ExtractCoordinates(n, coordinates));
}
编辑: 这是没有 linq 的,可能更容易理解:
void ParseCoordinateJSONNoLinq()
{
var coordinates = new List<int[]>();
var parsed = JObject.Parse(rawJSON);
var featureArray = parsed.SelectToken("features");
// These will be the objects with a "coordinates" key and an array value.
var coordArray = featureArray.Children();
foreach(var node in coordArray)
{
ExtractCoordinatesNoLinq(node.SelectToken("coordinates"), coordinates);
}
Console.WriteLine(string.Join("\n", coordinates.Select(c => $"({string.Join(", ", c)})")));
}
void ExtractCoordinatesNoLinq(JToken node, List<int[]> coordinates)
{
var intValues = new List<int>();
// Step through each child of this node and do something based on its node type.
foreach(var child in node.Children())
{
// If the child is an array, call this method recursively.
if (child.Type == JTokenType.Array)
{
// Changes to the coordinates list in the recursive call will persist.
ExtractCoordinatesNoLinq(child, coordinates);
// The child type is an integer, add it to the int values.
} else if (child.Type == JTokenType.Integer)
{
intValues.Add(child.Value<int>());
}
}
// Since we found int values at this level, add them to the shared coordinates list.
if (intValues.Count > 0)
{
coordinates.Add(intValues.ToArray());
}
}
如果您的其余数据是可靠的,我会使用典型的数据对象并对它们进行反序列化,然后添加类似上面的内容作为表示锯齿状数组的对象的 Custom JSON Converter。
public class MyDataObject {
public string SomeField {get; set;}
public Vector2 Position {get; set;}
[JsonProperty("features")]
public JaggedFeatures {get; set;}
}
public class JaggedFeatures {
public List<int[]> Coordinates {get; set;}
}
//...
JsonConvert.Deserialize<MyDataObject>(rawJSON, new JaggedFeaturesConverter())