2016-06-21 7 views
2

MarkLogicからのJSON応答を使用して、C#のモデルにバインドしています。関連するスニペットは以下の通りです:.NET内の配列内にJSONオブジェクトをバインドする

{ 
    "snippets":{ 
     "match":[ 
     { 
      "value":[ 
       "In (consolidated) enforcement actions for failure to answer subpoena, appeal from ", 
       { 
        "highlight":{ 
        "value":"judgement" 
        } 
       }, 
       " for defendants." 
      ] 
     } 
     ] 
    } 
} 

それは二つの文字列と別のJSONオブジェクトが含まれているので、私が午前問題は、外側の「値」配列です。この配列をC#でバインドする方法はありますか?私の現在のモデルは次のようになります。

[JsonProperty(PropertyName = "snippets")] 
public MarkLogicSnippetsModel Snippets { get; set; } 

public class MarkLogicSnippetsModel 
{ 
    [JsonProperty(PropertyName = "match")] 
    public IEnumerable<MarkLogicMatchModel> Matches { get; set; } 
} 

public class MarkLogicMatchModel 
{ 
    [JsonProperty(PropertyName = "value")] 
    public IEnumerable<string> Values { get; set; } 
} 

しかし、配列内のオブジェクトがある場合には動作しませんIEnumerable<string>を使用します。

+2

JSONが無効です。 –

+0

@PaulSwetzこれは返された応答の一部に過ぎないので、コピーしたときに有効ではなかった理由です – OstrichGlue

答えて

1

JSON自体はかなり恐ろしいですが、これは私がそれを扱える最高のコードモデルです。実際には値のデータを使用するためにはdynamicキーワードを使用する必要があります。本当にきれいに解析可能ではありません。現状では、それは3つの項目を持つ配列で、そのうち2つは文字列であり、それらの一つは、オブジェクトのハイライト "

public class Match 
{ 
    public List<object> value { get; set; } 
} 

public class Snippets 
{ 
    public List<Match> match { get; set; } 
} 

public class RootObject 
{ 
    public Snippets snippets { get; set; } 
} 
+0

私はそれが大したことではないことを認識しています。何かクリーナー。それが不可能な場合は、動的な提案を実装しようとします。 – OstrichGlue

+0

ウェイ値が2つの異なるものとして定義されていることも、マッピングクラスを作成するときに問題になります。 1つの場所では文字列、もう1つはオブジェクトです。 –

+0

JSONは、混合コンテンツを表現しようとしているためJSONが設計されていないため、「かなりひどい」です。 .NETオブジェクトへのバインドを容易にするために、JSONがどのようにフォーマットされているのか混合コンテンツをうまく扱うXMLとして結果を戻すのはどうでしょうか?スニペットをダウンストリームでどのように使用する予定ですか?たとえば、検索結果画面ではHTMLですか?それらをHTMLに変換し、.NETオブジェクトに文字列(HTML)を格納するだけで意味がありますか? –

1

あるJSであなたが持つことができるので、あなたが送っているJSONはJavaScriptの互換性があります異なるタイプのオブジェクト、文字列、数字などを配列内に格納します。

しかし、あなたは C#が強く配列を入力していているので、あなたがオブジェクトを置くことができない、文字列の配列でなければなりませ送るJSONでvalueを意味し、values配列はIEnumerable<string>であることを宣言しました。あなたが基本的にしようとしているのはこれです:

List<string> strings = new List<string>(); 
strings.Add("123"); 
strings.Add(new { foo: "foo" }); 

これは動作しません。

最も簡単な解決策は、JSONレイアウトをC#で有効に変更することです。そして、Value

public class Value 
{ 
    [JsonProperty(PropertyName = "text")] 
    public string Text{ get; set; } 
    [JsonProperty(PropertyName = "markup")] 
    public IEnumerable<Markup> Markup {get; set; } 
} 

ためのもう一つは、その後MarkLogicMatchModel

public class MarkLogicMatchModel 
{ 
    [JsonProperty(PropertyName = "value")] 
    public IEnumerable<Value> Values { get; set; } 
} 
を変更 Markup

public class Markup 
{ 
    [JsonProperty(PropertyName = "type")] 
    public string Type { get; set; } 
    [JsonProperty(PropertyName = "value")] 
    public string Value {get; set; } 
} 

のためのクラスを追加します

"match": [{ 
    "value": { 
     "text": "In (consolidated) enforcement actions for failure to answer subpoena, appeal from {0} for defendants.", 
     "markup": [{ 
      "type": "highlight", 
      "value" : "judgement" 
     }] 

    } 
}] 

: あなたはこれを使用することができます

後で、String.Formatを使用して、解析されたマークアップをテキストに追加することができます。 入力テキストに{または}が含まれておらず、コントロールするコンポーネントから入力されたものである場合は、これはうまく動作します。

これでうまくいかない場合は、代わりにdynamicを使用する必要があります。 here

+0

応答をありがとう - JSONを変更できるかどうかを私のチームの他のメンバーと話しています。そうでない場合は、私は動的な方法を見てみましょう。 – OstrichGlue

2

JSONは文字列「matches」の文字列が一致すると思われるようですが、In (consolidated) enforcement actions for failure to answer subpoena, appeal from judgement for defendants.というように、データモデルは文字列全体を再構成し、一致部分を取り出す。

public class RootObject 
{ 
    [JsonProperty(PropertyName = "snippets")] 
    public MarkLogicSnippetsModel Snippets { get; set; } 
} 

public class MarkLogicSnippetsModel 
{ 
    [JsonProperty(PropertyName = "match")] 
    public IEnumerable<MarkLogicMatchModel> Matches { get; set; } 
} 

public class MarkLogicMatchModel 
{ 
    [JsonProperty(PropertyName = "value")] 
    public List<MarkLogicMatchEntry> Values { get; set; } 
} 

public enum MatchType 
{ 
    Normal, 
    Highlight, 
} 

[JsonConverter(typeof(MarkLogicMatchEntryConverter))] 
public class MarkLogicMatchEntry 
{ 
    public MatchType MatchType { get; set; } 

    public string Value { get; set; } 
} 

次コンバータの使用:検索文字列の各セクションを表す。ここで

class MarkLogicMatchEntryConverter : JsonConverter 
{ 
    JsonSerializer GetEnumSerializer() 
    { 
     return JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = new[] { new StringEnumConverter { CamelCaseText = true } } }); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(MarkLogicMatchEntry); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     else if (reader.TokenType == JsonToken.String) 
     { 
      return new MarkLogicMatchEntry { MatchType = MatchType.Normal, Value = reader.Value.ToString() }; 
     } 
     else 
     { 
      var obj = JObject.Load(reader); 
      var property = obj.Properties().FirstOrDefault(); 
      var type = ((JValue)property.Name).ToObject<MatchType>(GetEnumSerializer()); 
      var value = (string)property.Value.SelectToken("value"); 

      return new MarkLogicMatchEntry { MatchType = type, Value = value }; 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var match = (MarkLogicMatchEntry)value; 
     if (match.MatchType == MatchType.Normal) 
     { 
      writer.WriteValue(match.Value); 
     } 
     else 
     { 
      var propertyName = (string)JToken.FromObject(match.MatchType, GetEnumSerializer()); 
      var obj = new JObject(new JProperty(propertyName, new JObject(new JProperty("value", match.Value)))); 
      obj.WriteTo(writer); 
     } 
    } 
} 

をJSONには、私は次のようなデータモデルをお勧めしたい、変更することはできないと仮定すると、

MarkLogicMatchEntryクラスによって。通常、一致しない部分文字列はMatchType = MatchType.Normalで表されます。一致する部分文字列はMatchType = MatchType.Highlightで表されます。理論的には、必要に応じてMatchType.Underlineなどの他のマッチタイプを追加することもできます。

関連する問題