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

时间:2014-03-17 22:29:55

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

帮助我使用json解析Newtonsoft.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(Polygon,LineString,Point)。

1 个答案:

答案 0 :(得分:4)

您可以使用自定义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<double>,和/或您可以为每种类型的复杂形状创建实际的类层次结构(例如Line,Polygon)并将它们组成Points。如果需要,修改转换器以创建这些对象并不困难。我会把那部分留给你。