我有一个.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回来的Body
上的StringResponse
属性获得此数据。我想将实际记录反序列化(我不需要或不需要took
,timed_out
等属性)到名为results
的C#对象中。为了做到这一点,我有:
var results = JsonConvert.DeserializeObject<List<Result>>(response.Body);
Result
类如下所示:
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; }
}
运行此命令时,出现以下错误:
无法将当前JSON对象反序列化为类型'System.Collections.Generic.List`1 [Result]',因为该类型需要JSON数组才能正确反序列化。
虽然该错误有意义,但我不知道如何解析hits
来提取_source
数据。 _source
属性包含我要反序列化的数据。其他所有内容只是我不在乎的元数据。
有没有办法做到这一点?如果可以,怎么办?
答案 0 :(得分:11)
您可以使用Json.Net的LINQ-to-JSON API来获取您感兴趣的节点,然后将其转换为结果列表:
axios.get('https://min-api.cryptocompare.com/data/all/coinlist')
.then(res => { // data
console.log(res.data) //console
})
.catch(function (error) { //errors
console.log(error);
});
const setAuthToken = token => {
if(token) {
axios.defaults.headers.common['Authorization'] = token;
} else {
delete axios.defaults.headers.common['Authorization']
}
};
正在运行的演示:https://dotnetfiddle.net/OkEpPA
答案 1 :(得分:8)
好吧,您DeserializeObject<T>
T
与Json不匹配。您的Json以{
开头,因此您的T必须是一个类(而不是IEnumerable
类型)。
让我们从外面开始,继续前进:
{
"took":31,
"timed_out":false,
"_shards": <object>
"hits": <object>
}
如此:
public class SearchResult
{
[JsonProperty("took")]
public int Took { get; set; }
[JsonProperty("timed_out")]
public bool TimedOut { get; set; }
[JsonProperty("_shards")]
public Shards Shards { get; set; }
[JsonProperty("hits")]
public Hits Hits { get; set; }
}
下一个是_shards
"_shards": {
"total":91,
"successful":91,
"skipped":0,
"failed":0
},
如此
public class Shards
{
[JsonProperty("total")]
public int Total { get; set; }
// etc...
}
然后hits
{
"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; }
}
然后Hits
列表:
{
"_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);
答案 2 :(得分:5)
您需要先反序列化为通用JToken
或JObject
,如下所示:
var token = JsonConvert.DeserializeObject<JToken>(jsonString);
然后您可以导航到保存您感兴趣的数据的 _source 属性:
var hitsArray = token["hits"]["hits"] as JArray;
var result = hitsArray[0]["_source"].ToObject<Result>();
答案 3 :(得分:2)
我使用http://json2csharp.com/将json转换为c#类 为了测试,我从http://easyonlineconverter.com/converters/dot-net-string-escape.html
的转换中得到了一个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; }
}
}
}
希望这会有所帮助
答案 4 :(得分:2)
尝试以下由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; }
}