【问题标题】:Json C# : deserializing a changing content or a piece of json responseJson C#:反序列化不断变化的内容或一段 json 响应
【发布时间】:2011-02-20 14:43:35
【问题描述】:

我使用的 Api 并非每次都返回基于所需位置的相同响应。有些地方有更多的细节,有些内容比其他地方有更多的属性。生成的序列化对象每次都不相同,导致不匹配时反序列化错误。这个项目的对象不是匹配整个内容响应,而是只匹配这个内容的一部分:Centroid。

{
   "place":{
      "woeid":12345,
      "placeTypeName":"State",
      "placeTypeName attrs":{
         "code":8
      },
      "name":"My Region",
      "country":"",
      "country attrs":{
         "type":"Country",
         "code":"XX"
      },
      "admin1":"My Region",
      "admin1 attrs":{
         "type":"Region",
         "code":""
      },
      "admin2":"",
      "admin3":"",
      "locality1":"",
      "locality2":"",
      "postal":"",
      "centroid":{
         "latitude":30.12345,
         "longitude":40.761292
      },
      "boundingBox":{
         "southWest":{
            "latitude":32.2799,
            "longitude":50.715958
         },
         "northEast":{
            "latitude":29.024891,
            "longitude":12.1234
         }
      },
      "areaRank":10,
      "popRank":0,
      "uri":"http:\/\/where.yahooapis.com",
      "lang":"en-US"
   }
}

有人可以指出反序列化一段内容而不是完整响应(质心不在同一位置)或反序列化不断变化的响应架构的最佳方法。

我使用 ServiceStack C# 序列化程序,但欢迎提出所有建议。谢谢。

【问题讨论】:

标签: c# json deserialization


【解决方案1】:

实际上有几种方法可以使用 ServiceStack 的 JsonSerializer 进行解析,如 example of parsing one of GitHub's JSON API 所示。

我会采用 JsonObject 方法,因为您最终会得到您选择的 C# 类,尽管它需要的不仅仅是您习惯使用 ServiceStack 的 JsonSerializer 的 1-liner。无论如何,这是生成的代码:

Func<JsonObject, Centroid> toCentroid = map => 
    new Centroid(map.Get<decimal>("latitude"), map.Get<decimal>("longitude"));

var place = JsonObject.Parse(JsonCentroid)
    .Object("place")
    .ConvertTo(x => new Place
    {
        WoeId = x.Get<int>("woeid"),
        PlaceTypeName = x.Get(""),
        PlaceTypeNameAttrs = x.Object("placeTypeName attrs"),
        Name = x.Get("Name"),
        Country = x.Get("Country"),
        CountryAttrs = x.Object("country attrs"),
        Admin1 = x.Get("admin1"),
        Admin1Attrs = x.Object("admin1 attrs"),
        Admin2 = x.Get("admin2"),
        Admin3 = x.Get("admin3"),
        Locality1 = x.Get("locality1"),
        Locality2 = x.Get("locality2"),
        Postal = x.Get("postal"),

        Centroid = x.Object("centroid")
            .ConvertTo(toCentroid),

        BoundingBox = x.Object("boundingBox")
            .ConvertTo(y => new BoundingBox
            {
                SouthWest = y.Object("southWest").ConvertTo(toCentroid),
                NorthEast = y.Object("northEast").ConvertTo(toCentroid)
            }),

        AreaRank = x.Get<int>("areaRank"),
        PopRank = x.Get<int>("popRank"),
        Uri = x.Get("uri"),
        Lang = x.Get("lang"),
    });

这里是full source code of this example

【讨论】:

    【解决方案2】:

    您可以使用 DataContractJsonSerializer,它是标准 .NET 框架的一部分。您只定义您感兴趣的那些属性。其他的将被忽略。

    class CentroidReader
    {
        public static Centroid ReadControid(Stream stream)
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Response));
            Response response = serializer.ReadObject(stream) as Response;
            return response.Place.Centroid;
        }
    }
    
    [DataContract]
    class Response
    {
        [DataMember(Name = "place")]
        public Place Place { get; set; }
    }
    
    [DataContract]
    class Place
    {
        [DataMember(Name = "centroid")]
        public Centroid Centroid { get; set; }
    }
    
    [DataContract]
    class Centroid
    {
        [DataMember(Name = "latitude")]
        public double? Latitude { get; set; }
        [DataMember(Name = "longitude")]
        public double? Longitude { get; set; }
    }
    

    【讨论】:

    • 谢谢科多。我很高兴使用 ServiceStack 得到其他人的回应。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多