C# 通过JSON.NET反序列化Elasticsearch结果
我有一个.NET应用程序,我想用它来查询Elasticsearch。我正在成功查询我的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":
{
"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; }
}