将数组和元素与JSON字符串分开

时间:2014-07-11 21:40:41

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

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

如果您查看它,您会看到实际结果数组在html_attributionsnext_page_token两个元素之后开始。

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

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

我得到一个空数组。

我的问题是,如何将html_attributionsnext_page_token字段分开,并从要反序列化的字符串中传递有效的results数组?

2 个答案:

答案 0 :(得分:2)

我不明白您希望分离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”的属性为string的属性。

同时属性“photos”是一个数组,为了反序列化它你必须创建另一个类并添加一个新创建的类的list / array类型的属性,它必须命名为“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;
    }

EDIT2: 如果你真的想要一个字符串[]作为结果,你可以使用上面的代码简单地使用System.Linq。

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

EDIT3: 您可以使用可在Newtonsoft.Json.Linq库中找到的JObject功能,而不是使用JavascriptSerializer。

    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方法可以查询而无需为反序列化创建强类型。

答案 1 :(得分:1)

我没有发现“[...]从要反序列化的字符串传递有效结果数组”

也许您需要切换到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...
}