2016-06-21 2 views
2

У меня есть ответ JSON от MarkLogic, который я привязываю к модели на C#. Соответствующий фрагмент кода ниже:Связанный объект JSON внутри массива в .NET

{ 
    "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 довольно ужасен, это лучшая модель кода, с которой я мог бы работать, вам нужно будет использовать динамическое ключевое слово, чтобы фактически использовать данные о значении ..... как верхний уровень " value 'используется не совсем чисто. Поскольку это стоит это массив, который имеет 3 пунктов, но два из них представляют собой строки и один из них является объектом «изюминкой»

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

Значение пути определяется как две разные вещи, также является проблемой при создании классов сопоставления. В одном месте его просто строка, а другая ее объект. –

+0

JSON «довольно ужасен», потому что он пытается представлять смешанный контент, для чего JSON не предназначен. Как бы вы предпочли увидеть форматированный JSON, чтобы упростить привязку к объектам .NET? Как получить результаты в формате XML, который хорошо обрабатывает смешанный контент? Как вы планируете использовать фрагменты вниз по течению? Как HTML, например, на экране результатов поиска? Имеет смысл преобразовать их в HTML и просто сохранить строку (HTML) в объекте .NET? –

1

вы отправляете JSON является JavaScript совместимы, потому что в JS вы можете иметь различные типы объектов, строки, числа и т. д. в массиве.

Но вы объявили о values массиве быть IEnumerable<string>, что означает value в формате JSON вы отправляете должна быть массивом строк, вы не можете поместить объект, потому что C# является сильно типизированным массивами. Что вы в основном пытаетесь сделать, так это:

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

Это не сработает.

Самое простое решение - изменить макет JSON, чтобы он был действительным для C#. Вы могли бы использовать это:

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

    } 
}] 

Добавить класс для Markup

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

Затем еще один для 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; } 
} 

Позже вы можете использовать String.Format, чтобы добавить разглаженную разметку в текст. Это будет работать, если входной текст не содержит { или }, и если он исходит из компонента, которым вы управляете, конечно.

Если это не сработает, вам нужно будет использовать dynamic, как предложил Пол, нет другого пути. Подробнее об этом here

+0

Спасибо за ответ. Я разговариваю с другими членами моей команды, чтобы узнать, можем ли мы изменить JSON. Если нет, я взгляну на динамический путь. – OstrichGlue

2

Похоже, что JSON должен представлять совпадения в некоторой общей строке, в этом случае совпадение строки «суждение» в In (consolidated) enforcement actions for failure to answer subpoena, appeal from judgement for defendants. Таким образом, ваша модель данных должна будет иметь возможность восстановить всю строку, а также выбрать соответствующую часть.

Предполагая, что JSON не может быть изменен, я хотел бы предложить модель данных, как следующее:

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

Здесь каждую секцию досматриваемой строки представлена классом MarkLogicMatchEntry. Обычные, непревзойденные подстроки представлены MatchType = MatchType.Normal. Соответствующие подстроки представлены MatchType = MatchType.Highlight. Теоретически могут быть добавлены другие типы соответствия, такие как MatchType.Underline.

Смежные вопросы