elasticsearch,json.net,C#,elasticsearch,Json.net" /> elasticsearch,json.net,C#,elasticsearch,Json.net" />

C# 通过JSON.NET反序列化Elasticsearch结果

C# 通过JSON.NET反序列化Elasticsearch结果,c#,elasticsearch,json.net,C#,elasticsearch,Json.net,我有一个.NET应用程序,我想用它来查询Elasticsearch。我正在成功查询我的Elasticsearch索引。结果与此类似: { "took":31, "timed_out":false, "_shards": { "total":91, "successful":91, "skipped":0, "failed":0 }, "hits":{ "total":1, "max_score":1.0, "hits":

我有一个.NET应用程序,我想用它来查询Elasticsearch。我正在成功查询我的Elasticsearch索引。结果与此类似:

{
  "took":31,
  "timed_out":false,
  "_shards": {
    "total":91,
    "successful":91,
    "skipped":0,
    "failed":0
  },
  "hits":{
    "total":1,
    "max_score":1.0,
    "hits":[
      {
        "_index":"my-index",
        "_type":"doc",
        "_id":"TrxrZGYQRaDom5XaZp23",
        "_score":1.0,
        "_source":{
          "my_id":"65a107ed-7325-342d-adab-21fec0a97858",
          "host":"something",
          "zip":"12345"
        }
      },
    ]
  }
}
现在,这些数据可以通过我从Elasticsearch获得的StringResponse上的Body属性获得。我想将我不想要或不需要的take、timed_out等属性的实际记录反序列化到名为results的C对象中。为了做到这一点,我有:

var results = JsonConvert.DeserializeObject<List<Result>>(response.Body);
当我运行此操作时,会出现以下错误:

无法将当前JSON对象反序列化为“System.Collections.Generic.List`1[Result]”类型,因为该类型需要JSON数组才能正确反序列化

虽然这个错误是有道理的,但我不知道如何解析点击来提取源数据。_source属性包含我要反序列化的数据。其他的都是元数据,我不在乎


有办法做到这一点吗?如果是,如何实现?

您需要首先反序列化到通用JToken或JObject,如下所示:

public class Result
{
  [JsonProperty(PropertyName = "my_id")]
  public string Id { get; set; }

  [JsonProperty(PropertyName = "host")]
  public string Host { get; set; }

  [JsonProperty(PropertyName = "zip")]
  public string PostalCode { get; set; }
}
var token = JsonConvert.DeserializeObject<JToken>(jsonString);
然后,您可以导航到保存您感兴趣的数据的_source属性:

var hitsArray = token["hits"]["hits"] as JArray;
var result = hitsArray[0]["_source"].ToObject<Result>();
您可以使用Json.Net仅获取感兴趣的节点,然后将其转换为结果列表:

var results = JToken.Parse(response.Body)
                    .SelectTokens("hits.hits[*]._source")
                    .Select(t => t.ToObject<Result>())
                    .ToList();
正在工作的演示:

您反序列化的对象T与Json不匹配。Json以{开头,因此T必须是类而不是IEnumerable类型

让我们从外面开始,在里面工作:

{
  "took":31,
  "timed_out":false,
  "_shards": <object>
  "hits": <object>
}
接下来是(u shards)

所以

然后击中

所以

一旦您创建了所有需要的文件,那么您就可以反序列化:

JsonConvert.DeserializeObject<SearchResult>(json);
我曾经将json转换为c类 在我的测试中,我从上的转换中得到了一个json字符串

然后,我创建了一个具有此类的控制台应用程序:

using System.Collections.Generic;
using Newtonsoft.Json;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = "{  \"took\":31,  \"timed_out\":false,  \"_shards\": {    \"total\":91,    \"successful\":91,    \"skipped\":0,    \"failed\":0  },  \"hits\":{    \"total\":1,    \"max_score\":1.0,    \"hits\":[      {        \"_index\":\"my-index\",        \"_type\":\"doc\",        \"_id\":\"TrxrZGYQRaDom5XaZp23\",        \"_score\":1.0,        \"_source\":{          \"my_id\":\"65a107ed-7325-342d-adab-21fec0a97858\",          \"host\":\"something\",          \"zip\":\"12345\"        }      },    ]  }}";
            RootObject t = JsonConvert.DeserializeObject<RootObject>(json);
        }

        public class Shards
        {
            public int total { get; set; }
            public int successful { get; set; }
            public int skipped { get; set; }
            public int failed { get; set; }
        }

        public class Source
        {
            public string my_id { get; set; }
            public string host { get; set; }
            public string zip { get; set; }
        }

        public class Hit
        {
            public string _index { get; set; }
            public string _type { get; set; }
            public string _id { get; set; }
            public double _score { get; set; }
            public Source _source { get; set; }
        }

        public class Hits
        {
            public int total { get; set; }
            public double max_score { get; set; }
            public List<Hit> hits { get; set; }
        }

        public class RootObject
        {
            public int took { get; set; }
            public bool timed_out { get; set; }
            public Shards _shards { get; set; }
            public Hits hits { get; set; }
        }
    }
}

希望这有助于

尝试VS特殊粘贴功能生成的以下结构:

    public class Rootobject
{
    public int took { get; set; }
    public bool timed_out { get; set; }
    public _Shards _shards { get; set; }
    public Hits hits { get; set; }
}

public class _Shards
{
    public int total { get; set; }
    public int successful { get; set; }
    public int skipped { get; set; }
    public int failed { get; set; }
}

public class Hits
{
    public int total { get; set; }
    public float max_score { get; set; }
    public Hit[] hits { get; set; }
}

public class Hit
{
    public string _index { get; set; }
    public string _type { get; set; }
    public string _id { get; set; }
    public float _score { get; set; }
    public _Source _source { get; set; }
}

public class _Source
{
    public string my_id { get; set; }
    public string host { get; set; }
    public string zip { get; set; }
}

有没有办法反序列化[点击][点击]属性直接转换为列表?或任何其他类型的结果对象集合?从性能角度来看,一次转换一个对象似乎很昂贵。Brian Rogers的答案将其转换为列表。由于所有令牌总是在幕后一次转换一个,因此其效率很难比他建议的高。
{
  "total":1,
  "max_score":1.0,
  "hits": <IEnumerable because []>
}
public class Hits
{
  [JsonProperty("total")]
  public int Total { get; set; }
  [JsonProperty("max_score")]
  public int MaxScore { get; set; }
  [JsonProperty("hits")]
  public List<Hit> Hits { get; set; }
}
{
    "_index":"my-index",
    "_type":"doc",
    "_id":"TrxrZGYQRaDom5XaZp23",
    "_score":1.0,
    "_source":  <object>
},
public class Hit
{
  [JsonProperty("_index")]
  public string Index { get; set; }
  // etc
}
JsonConvert.DeserializeObject<SearchResult>(json);
using System.Collections.Generic;
using Newtonsoft.Json;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = "{  \"took\":31,  \"timed_out\":false,  \"_shards\": {    \"total\":91,    \"successful\":91,    \"skipped\":0,    \"failed\":0  },  \"hits\":{    \"total\":1,    \"max_score\":1.0,    \"hits\":[      {        \"_index\":\"my-index\",        \"_type\":\"doc\",        \"_id\":\"TrxrZGYQRaDom5XaZp23\",        \"_score\":1.0,        \"_source\":{          \"my_id\":\"65a107ed-7325-342d-adab-21fec0a97858\",          \"host\":\"something\",          \"zip\":\"12345\"        }      },    ]  }}";
            RootObject t = JsonConvert.DeserializeObject<RootObject>(json);
        }

        public class Shards
        {
            public int total { get; set; }
            public int successful { get; set; }
            public int skipped { get; set; }
            public int failed { get; set; }
        }

        public class Source
        {
            public string my_id { get; set; }
            public string host { get; set; }
            public string zip { get; set; }
        }

        public class Hit
        {
            public string _index { get; set; }
            public string _type { get; set; }
            public string _id { get; set; }
            public double _score { get; set; }
            public Source _source { get; set; }
        }

        public class Hits
        {
            public int total { get; set; }
            public double max_score { get; set; }
            public List<Hit> hits { get; set; }
        }

        public class RootObject
        {
            public int took { get; set; }
            public bool timed_out { get; set; }
            public Shards _shards { get; set; }
            public Hits hits { get; set; }
        }
    }
}
    public class Rootobject
{
    public int took { get; set; }
    public bool timed_out { get; set; }
    public _Shards _shards { get; set; }
    public Hits hits { get; set; }
}

public class _Shards
{
    public int total { get; set; }
    public int successful { get; set; }
    public int skipped { get; set; }
    public int failed { get; set; }
}

public class Hits
{
    public int total { get; set; }
    public float max_score { get; set; }
    public Hit[] hits { get; set; }
}

public class Hit
{
    public string _index { get; set; }
    public string _type { get; set; }
    public string _id { get; set; }
    public float _score { get; set; }
    public _Source _source { get; set; }
}

public class _Source
{
    public string my_id { get; set; }
    public string host { get; set; }
    public string zip { get; set; }
}