【问题标题】:Parse single values from HttpResponse从 HttpResponse 解析单个值
【发布时间】:2019-02-21 22:38:34
【问题描述】:

在调用 Google Geolocation API 时,结果 (json) 会像这样返回

示例(抱歉,我无法正确格式化 Json)

{"geocoded_waypoints" : [
  {
     "geocoder_status" : "OK",
     "place_id" : "EiQ3LCA3IExha2VzaWRlIERyLCBSeWUsIE5ZIDEwNTgwLCBVU0EiHRobChYKFAoSCQH00P0vl8KJEQ2d7mWAl0jrEgE3",
     "types" : [ "subpremise" ]
  },
  {
     "geocoder_status" : "OK",
     "place_id" : "ChIJ1YqpR4eRwokRTuazxMrnKiM",
     "types" : [ "establishment", "point_of_interest" ]
  }   ],
"routes" : [{
     "bounds" : {
        "northeast" : {
           "lat" : 41.0044903,
           "lng" : -73.6892836
        },
        "southwest" : {
           "lat" : 40.9575099,
           "lng" : -73.7589093
        }
     },
     "copyrights" : "Map data ©2018 Google",
     "legs" : [
        {
           "distance" : {
              "text" : "7.0 mi",
              "value" : 11325
           },
           "duration" : {
              "text" : "15 mins",
              "value" : 889
           },
           "end_address" : "851 Fenimore Rd, Mamaroneck, NY 10543, USA",
           "end_location" : {
              "lat" : 40.9575099,
              "lng" : -73.75338219999999
           },
           "start_address" : "7 Pheasant Run #7, Rye, NY 10580, USA",
           "start_location" : {
              "lat" : 40.99850199999999,
              "lng" : -73.689633
           },

我需要从返回的数据中检索各种单个项目,例如,持续时间:文本值。 有没有办法过滤掉 API 调用中的多余部分,或者我如何从 Json 中解析它?

我尝试反序列化为一个对象,然后对其进行迭代并获取腿数组,但是 A. 这不起作用,因为该对象位于大项目上,而不是集合上,而 B. 这似乎很浪费。

 public int TravelTimeInMinutes(string origin, string destination, string apiKey)
    {
        var timeToTravel = 0;

        var url = DirectionsUrlBase + ConvertOriginFormat(origin) + ConvertDestinationFormat(destination) + "&key="+ apiKey;
        var client = new HttpClient();

        // Add the Accept type header for JSON format.
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        // get the response
        // make method async once working
         var response = client.GetAsync(url).Result;   
        if (response.IsSuccessStatusCode)
        {
            // Parse the response body.
            var result = JsonConvert.SerializeObject(response.Content.ReadAsStringAsync().Result());
            dynamic array = JsonConvert.DeserializeObject(result);
            foreach (var item in array)
            {

            }
          //… rest removed for brevity

如何深入检索单个值?我认为我的错误在于我如何反序列化响应。我还有一个带有 Text 和 Value 属性的 Duration 类。如果可能的话,我想反序列化到那个类。

跟进

我在序列化调用之后添加了.Result response.Content.ReadAsStringAsync().Result()

现在返回正确的 json

现在我怎样才能从中解析单个值,或者我可以反序列化到 Duration 类中。 根据查尔斯的建议

我有一个根对象

公共类 MapsDirectionObject { 公共 GeocodedWaypoints[] geocoded_waypoints { 获取;放; } 公共路线[]路线{获取;放; } }

public class Routes
{
    public object[] Value { get; set; }
}

public class GeocodedWaypoints
{
    public string geocoder_status { get; set; }
    public string place_id { get; set; }
    public string[] types { get; set; }
}

由于返回的 json 只有两个主要的子类,路线和航路点,所以我也有这些类。带有以下错误的反序列化错误。

Newtonsoft.Json.JsonSerializationException: '错误转换值 "{ "geocoded_waypoints" : [ {

如果我删除序列化的 .Result 调用,我可以映射到该对象,但值为 null。

【问题讨论】:

    标签: c# json http


    【解决方案1】:

    首先,请在您的答案上发布一个完整有效的 JSON 对象。

    您使用 Visual Studio 进行编码,对吗?您可以使用选择性粘贴来帮助您:

    1) 将整个 JSON 复制到剪贴板;

    2) 在 Visual Studio 上打开你的类文件;

    3) 转到菜单“编辑 > 选择性粘贴 > 粘贴为 JSON 类”;

    4) 你会得到这样的东西:

    public class Rootobject
    {
        public Geocoded_Waypoints[] geocoded_waypoints { get; set; }
    }
    
    public class Geocoded_Waypoints
    {
        public string geocoder_status { get; set; }
        public string place_id { get; set; }
        public string[] types { get; set; }
    }
    

    现在您可以反序列化为类型化对象:

    var myObject = JsonConvert.DeserializeObject<Rootobject>(result);
    
    foreact(var geocoded_waypoints in myObject.geocoded_waypoints)
    {
        // do something with geocoded_waypoints
    }
    
    // your duration object:
    var duration = myObject.routes[0].legs[0].duration;
    

    如果您愿意,您可以将 Rootobject 重命名为您想要的任何名称,例如 Geolocation。

    【讨论】:

    • ...我没有完整的返回对象,因为返回的数据比我需要的要多得多。很想知道它是否可过滤,例如在腿上请求的方式:持续时间数据。我有一个持续时间课程。查看我对 OP 的后续补充
    • 使用完整的 JSON 文件执行这些步骤,您将拥有所有对象树,您将需要它进行反序列化,然后只获取您需要的内容并可能放入另一个模型中
    • 另外,我的编辑菜单上没有选择性粘贴选项
    • 您使用的是什么版本的 VS?请参阅此修复:social.msdn.microsoft.com/Forums/sqlserver/en-US/…
    • VS 2017 专业版
    【解决方案2】:

    首先我希望我们进行强类型反序列化,所以让我们创建与我们需要的 JSON 数据对应的类:

    public class ResultData
    {
        [JsonProperty("routes")]
        public List<Route> Routes { get; set; }
    }
    
    public class Route
    {
        [JsonProperty("legs")]
        public List<Leg> Legs { get; set; }
    }
    
    public class Leg
    {
        [JsonProperty("duration")]
        public Duration Duration { get; set; }
    }
    
    public class Duration
    {
        [JsonProperty("text")]
        public string Text { get; set; }
        [JsonProperty("value")]
        public int Value { get; set; }
    }
    

    然后我们反序列化 JSON:

    var client = new HttpClient();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    var response = client.GetAsync("https://maps.googleapis.com/maps/api/directions/json?origin=7+7+Lakeside+Dr+Rye+NY&destination=Winged+Winged+Foot+Golf+Club").Result;
    if (response.IsSuccessStatusCode)
    {
        var desed = JsonConvert.DeserializeObject<ResultData>(response.Content.ReadAsStringAsync().Result);
        var durations = desed.Routes.SelectMany(r => r.Legs.Select(l => l.Duration)).ToList();
        durations.ForEach(d => Console.WriteLine($"T: {d.Text}, V: {d.Value}"));
    }
    

    注意:

    跳过序列化步骤...ReadAsStringAsync() 应该生成一个有效的 JSON 字符串

    【讨论】:

    • 上述方法都不起作用(两个答案)。我收到无法转换数据的错误
    • @dinotom 尝试使用 `JsonProperty' 属性
    • 你能提供一个有效的json来测试吗?
    • @dinotom 我注意到有一个名为 Result 的根对象我根据需要更改了答案
    • 我发布了完整的 json
    猜你喜欢
    • 2012-10-03
    • 2011-06-25
    • 2011-02-20
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2011-12-28
    相关资源
    最近更新 更多