web-dev-qa-db-ja.com

JSON.NETを介したElasticsearch結果の逆シリアル化

Elasticsearchのクエリに使用する.NETアプリケーションがあります。 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"
        }
      },
    ]
  }
}

現在、このデータはBodyStringResponseプロパティを介して取得できます。Elasticsearchから取得しています。実際のレコードを逆シリアル化したい(tooktimed_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プロパティには、逆シリアル化するデータが含まれています。他のすべては私が気にしないメタデータです。

これを行う方法はありますか?もしそうなら、どうですか?

19
user687554

Json.Netの LINQ-to-JSON API を使用して、関心のあるノードのみを取得し、それらを結果のリストに変換できます。

var results = JToken.Parse(response.Body)
                    .SelectTokens("hits.hits[*]._source")
                    .Select(t => t.ToObject<Result>())
                    .ToList();

作業デモ: https://dotnetfiddle.net/OkEpPA

12
Brian Rogers

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);
8
Erik Philips

次のように、まずジェネリックJTokenまたはJObjectに逆シリアル化する必要があります。

var token = JsonConvert.DeserializeObject<JToken>(jsonString);

次に、目的のデータを保持する_ sourceプロパティに移動できます。

var hitsArray = token["hits"]["hits"] as JArray;
var result = hitsArray[0]["_source"].ToObject<Result>();
5
thepirat000

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; }
}
2
MoeZir

私は http://json2csharp.com/ を使用してjsonをc#クラスに変換し、私のテストでは http://easyonlineconverter.com/convertersで行われた変換からjson文字列を取得しました/dot-net-string-escape.html

次に、このクラスでコンソールアプリを作成しました。

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; }
        }
    }
}

お役に立てれば

2
Rena