【问题标题】:Parse json with different types value (Newtonsoft.Json)解析具有不同类型值的 json (Newtonsoft.Json)
【发布时间】:2014-03-17 22:29:55
【问题描述】:

帮我解析jsonNewtonsoft.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]
            ]
        },
}

coordinates 的类型为 List<double>List<List<double>>,具体取决于键 type(多边形、线串、点)。

【问题讨论】:

标签: c# json windows-phone-7 windows-phone-8 json.net


【解决方案1】:

您可以使用自定义JsonConverter 解决此问题。转换器可以加载每个形状的数据,查看type 字段,然后相应地填充坐标数组。实际上,如果您愿意,转换器可以在这里执行双重任务,以便在我们处理数据时将数据扁平化为更简单的类结构。鉴于您提供的 JSON,这就是我的做法。

首先,定义一个类来保存反序列化的形状数据。我们将反序列化为这些列表:

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

接下来创建转换器类。这负责将每个形状的 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();
    }
}

[JsonConverter] 属性添加到Shape 类以将其绑定到ShapeConverter

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

剩下的就是反序列化 JSON,我们可以这样做:

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

这里有一个测试程序来演示:

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

输出:

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)

如果你想要更花哨,你可以为每个坐标使用Point 结构而不是List&lt;double&gt;,和/或你可以为每种类型的复杂形状(例如线、多边形)创建一个实际的类层次结构) 并将它们组合成Points。如果需要,修改转换器以创建这些对象并不难。我会把这部分留给你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    相关资源
    最近更新 更多