简体   繁体   English

解析具有不同类型值的json(Newtonsoft.Json)

[英]Parse json with different types value (Newtonsoft.Json)

Help me parse the json with Newtonsoft.Json . 帮我用Newtonsoft.Json解析json

  {
    "_id": 160,
    "location": {
        "type": "Point",
        "coordinates": [43.59043144045182, 39.72119003534317]
    },  
},
{
    "_id": 161, 
    "location": {
        "type": "LineString",
        "coordinates": [
            [43.58780105200211, 39.719191789627075],
            [43.58817794899264, 39.719465374946594]
        ]
    },  
},
{
    "_id": 152, 
        "location": {
            "type": "Polygon",
            "coordinates": [
                [43.590524759627954, 39.71930980682373],
                [43.590474249766544, 39.71926689147949],
                [43.59043151061995, 39.71934735774994],
                [43.59073456936772, 39.71958339214325],
                [43.59076565222992, 39.71949219703674]
            ]
        },
}

Key coordinates has type List<double> or List<List<double>> depending on the key type (Polygon, LineString, Point). 关键点coordinates类型为List<double>List<List<double>>具体取决于关键点type (多边形,LineString,Point)。

You can solve this problem using a custom JsonConverter . 您可以使用自定义JsonConverter解决此问题。 The converter can load the data for each shape, look at the type field and then populate the coordinates array accordingly. 转换器可以加载每种形状的数据,查看type字段,然后相应地填充坐标数组。 And actually, if you want, the converter can do double-duty here to flatten the data down into a simpler class structure while we're at it. 实际上,如果您愿意,转换器可以在此处执行双重任务,以在我们使用数据时将数据压缩为更简单的类结构。 Here's how I would do it, given the JSON you have presented. 给定您提供的JSON,这就是我的处理方法。

First, define a class to hold the deserialized shape data. 首先,定义一个类来保存反序列化的形状数据。 We'll deserialize into a list of these: 我们将反序列化为以下列表:

class Shape
{
    public int Id { get; set; }
    public string Type { get; set; }
    public List<List<double>> Coordinates { get; set; }
}

Next create the converter class. 接下来创建转换器类。 This is responsible for transforming the JSON for each shape into a concrete Shape object. 这负责将每个形状的JSON转换为具体的Shape对象。

class ShapeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Shape));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        Shape shape = new Shape();
        shape.Id = (int)jo["_id"];
        shape.Type = (string)jo["location"]["type"];
        JArray ja = (JArray)jo["location"]["coordinates"];
        if (shape.Type == "Point")
        {
            shape.Coordinates = new List<List<double>>();
            shape.Coordinates.Add(ja.ToObject<List<double>>());
        }
        else
        {
            shape.Coordinates = ja.ToObject<List<List<double>>>();
        }
        return shape;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Add a [JsonConverter] attribute to the Shape class to tie it to the ShapeConverter : Shape类添加[JsonConverter]属性,将其绑定到ShapeConverter

[JsonConverter(typeof(ShapeConverter))]
class Shape
{
    ...
}

All that is left is to deserialize the JSON, which we can do like this: 剩下的就是反序列化JSON,我们可以这样进行:

List<Shape> shapes = JsonConvert.DeserializeObject<List<Shape>>(json);

Here is a test program to demonstrate: 这是一个演示程序:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        [
            {
                ""_id"": 160,
                ""location"": {
                    ""type"": ""Point"",
                    ""coordinates"": [ 43.59043144045182, 39.72119003534317 ]
                }
            },
            {
                ""_id"": 161,
                ""location"": {
                    ""type"": ""LineString"",
                    ""coordinates"": [
                        [ 43.58780105200211, 39.719191789627075 ],
                        [ 43.58817794899264, 39.719465374946594 ]
                    ]
                }
            },
            {
                ""_id"": 152,
                ""location"": {
                    ""type"": ""Polygon"",
                    ""coordinates"": [
                        [ 43.590524759627954, 39.71930980682373 ],
                        [ 43.590474249766544, 39.71926689147949 ],
                        [ 43.59043151061995, 39.71934735774994 ],
                        [ 43.59073456936772, 39.71958339214325 ],
                        [ 43.59076565222992, 39.71949219703674 ]
                    ]
                }
            }
        ]";

        List<Shape> shapes = JsonConvert.DeserializeObject<List<Shape>>(json);

        foreach (Shape shape in shapes)
        {
            Console.WriteLine("Id: " + shape.Id);
            Console.WriteLine("Type: " + shape.Type);
            Console.WriteLine("Coordinates: ");
            foreach (List<double> point in shape.Coordinates)
            {
                Console.WriteLine("   (" + point[0] + ", " + point[1] + ")");
            }
            Console.WriteLine();
        }
    }
}

Output: 输出:

Id: 160
Type: Point
Coordinates:
   (43.5904314404518, 39.7211900353432)

Id: 161
Type: LineString
Coordinates:
   (43.5878010520021, 39.7191917896271)
   (43.5881779489926, 39.7194653749466)

Id: 152
Type: Polygon
Coordinates:
   (43.590524759628, 39.7193098068237)
   (43.5904742497665, 39.7192668914795)
   (43.59043151062, 39.7193473577499)
   (43.5907345693677, 39.7195833921433)
   (43.5907656522299, 39.7194921970367)

If you want to get more fancy, you can use a Point struct instead of a List<double> for each coordinate, and/or you can create an actual class hierarchy for each type of complex shape (eg Line, Polygon) and compose them of Points . 如果想获得更多效果,可以为每个坐标使用Point结构而不是List<double> ,并且/或者可以为每种复杂形状(例如,Line,Polygon)创建实际的类层次结构并进行组合Points It would not be difficult to modify the converter to create these objects if desired. 如果需要,修改转换器以创建这些对象将不难。 I'll leave that part to you. 我会把那部分留给你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM