【问题标题】:Separating array and element from a JSON string从 JSON 字符串中分离数组和元素
【发布时间】:2014-07-11 21:40:40
【问题描述】:

我正在连接您Google Places API 以以JSON 字符串的形式检索结果。可以查看字符串Here的完整格式。

如果您查看它,您会发现实际结果数组在两个元素之后开始,即html_attributions 和next_page_token。

所以当我尝试以这种方式反序列化它时:

var serializer = new JavaScriptSerializer();
var arr= serializer.Deserialize(result,typeof(string[]));

我得到一个空数组。

我的问题是,有什么方法可以分隔 html_attributions 和 next_page_token 字段并从要反序列化的字符串中传递有效的 results 数组?

【问题讨论】:

    标签: c# .net json google-places-api


    【解决方案1】:

    我不明白您希望将 html_attributions 和 next_page_token 分开的部分。

    仅使用您需要的任何属性反序列化响应还不够吗?

    例如,您可以反序列化响应以仅检索您想要的值;

        // I represent the wrapper result
        class Result
        {
            public List<string> html_attributions { get; set; }
    
            public string next_page_token { get; set; }
    
            public List<ResultItem> results { get; set; }
        }
    
        // I represent a result item
        class ResultItem
        {
            public string id { get; set; }
    
            public string name { get; set; }
        }
    
        // the actual deserialization
        Result Deserialize(string json)
        {
            var serializer = new JavaScriptSerializer();
            return serializer.Deserialize(json, typeof(Result));
        }
    

    编辑: 您的反序列化不返回字符串数组的原因是因为您检索的响应实际上是一个对象而不是数组,但是该对象中名为 results 的参数是一个数组。为了让您反序列化更多属性,您必须在“ResultItem”类中定义它们,抱歉我在这里命名不佳。

    例如,如果您还希望检索每个结果的图标属性,则必须添加一个名为“icon”的字符串类型的属性。

    同时属性“photos”是一个数组,为了反序列化它,您必须创建另一个类并添加该新创建类的列表/数组类型的属性,并且它必须命名为“photos”除非您使用不同的序列化程序或使用 DataContract 和 DataMember 属性(使用 Name 属性进行字段映射)。

        // the representation of a photo within a result item
        class Photo
        {
            public int height { get; set; }
    
            public List<string> html_attributions { get; set; }
    
            public string photo_reference { get; set; }
    
            public int width { get; set; }
        }
    
        // I represent a result item
        class ResultItem
        {
            public string id { get; set; }
    
            public string name { get; set; }
    
            // the added icon
            public string icon { get; set; }
    
            // the added photos collection, could also be an array
            public List<Photo> photos { get; set; }
        }
    

    只需查看 JSON 结果,找出您可能想要添加的其他属性,例如“scope”属性是一个字符串,而“price_level”是一个整数。

    如果我正确理解您的评论,您只对实际结果感兴趣,您仍然需要使用其包装器正确反序列化响应。

        // the actual deserialization
        List<ResultItem> Deserialize(string json)
        {
            var serializer = new JavaScriptSerializer();
            var result = serializer.Deserialize(json, typeof(Result));
    
            return result.results;
        }
    

    编辑2: 如果你真的想要一个 string[] 作为结果,你可以简单地使用 System.Linq 使用上面的代码。

    string[] stringArray = result.results.Select(r => string.Format("id:{0} - name:{1}", r.id, r.name)).ToArray();
    

    编辑3: 除了使用 JavascriptSerializer,您还可以使用 Newtonsoft.Json.Linq 库中的 JObject 功能。

        var jsonObject = JObject.Parse(json);
    
        string[] results = jsonObject.SelectTokens("results").Select(r => r.ToString()).ToArray();
    

    这将为您提供一个字符串数组,其中数组中的每个值都是每个结果的实际 json 字符串。

    如果您只想查询坐标:

        var jsonObject = JObject.Parse(json);
    
        var coordinates = jsonObject["results"]
                .Select(x => x.SelectToken("geometry").SelectToken("location"))
                .Select(x => string.Format("{0},{1}", (string)x.SelectToken("lat"), (string)x.SelectToken("lng")))
                .ToArray();
    

    这会给你一个坐标数组,例如:

    [
        "-33.867217,151.195939",
        "-33.866786,151.195633",
        ...
    ]
    

    无论您选择哪种方法,您都可以使用 Newtonsoft 或 .net 序列化程序实现相同的结果,而 Newtonsoft 方法允许您在不创建强类型进行反序列化的情况下进行查询。

    【讨论】:

    • 这几乎是我所需要的完美,只是最后一件事,现在我有一个包含所有这些值的对象,但是我如何将这个object 转换为List 的string[]?
    • 我想做string [] arr = result.results;之类的事情,但我不能因为我得到Cannot implicitly convert type 'System.Collections.Generic.List&lt;abc.Models.model&gt;' to 'string[]'
    • 再次编辑,但是我不明白如果您只打算将响应作为字符串值使用,为什么要反序列化响应。也许您应该看看 Newtonsoft 或任何其他允许您查询 json 对象的库。
    【解决方案2】:

    我没有找到的重点“[...]从要反序列化的字符串中传递有效的结果数组”。

    也许您需要切换到JSON.NET 并执行以下操作:

    // You simply deserialize the entire response to an ExpandoObject
    // so you don't need a concrete type to deserialize the whole response...
    dynamic responseEntity = JsonConvert.DeserializeObject<ExpandoObject>(
                                 googlePlacesJson, new ExpandoObjectConverter()
                             );
    
    // Now you can access result array as an `IEnumerable<dynamic>`...
    IEnumerable<dynamic> results = responseEntity.results;
    
    foreach(dynamic result in results)
    {
       // Do stuff for each result in the whole response...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-29
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      • 2012-08-29
      • 2021-10-15
      • 1970-01-01
      相关资源
      最近更新 更多