2016-08-03 7 views
2

Я пытаюсь десериализовать содержимое строки в объект, но я хочу, чтобы содержимое было чувствительным к регистру. Код должен быть успешным только в том случае, если строка имеет свойства нижнего регистра и сбой, если она имеет свойства верхнего регистра. Ниже приведен класс:JsonConvert DeserializeObject с учетом регистра

internal class ResponseList 
{ 
    [DataMember] 
    [JsonProperty] 
    internal List<Response> Value { get; set; } 
} 

internal class Response 
{ 
    [DataMember] 
    [JsonProperty] 
    internal string Id { get; set; } 

    [DataMember] 
    [JsonProperty] 
    internal string Location { get; set; } 

    [DataMember] 
    [JsonProperty] 
    internal PlanClass Plan { get; set; } 
} 

internal class PlanClass 
{ 
    [DataMember] 
    [JsonProperty] 
    internal string Name { get; set; } 

    [DataMember] 
    [JsonProperty] 
    internal string Product { get; set; } 

    [DataMember] 
    [JsonProperty] 
    internal string Publisher { get; set; } 
} 

Ниже приведен код, который у меня есть. Но это не чувствительно к регистру. Он преуспевает как для верхнего и нижнего регистра:

string content = File.ReadAllText(contentFilePath); 
JsonSerializerSettings jsonSerializerSettings1 = new JsonSerializerSettings() 
{ 
    ContractResolver = new CamelCasePropertyNamesContractResolver() 
}; 
ResponseList response = (ResponseList)JsonConvert.DeserializeObject(contentResourceOutput, typeof(ResponseList), Constants.JsonSerializerSettings); 

Код должен быть успешной только если содержание:

{ 
    "value": [ 
    { 
     "id": "id1", 
     "location": "location1", 
     "plan": { 
     "name": "free", 
     "product": "product1", 
     "publisher": "publisher1" 
     } 
    } 
    ] 
} 

и потерпеть неудачу, если даже если одна из клавиш верхнего регистра. Например.

{ 
    "value": [ 
    { 
     "Id": "id1", 
     "Location": "location1", 
     "plan": { 
     "Name": "free", 
     "product": "product1", 
     "publisher": "publisher1" 
     } 
    } 
    ] 
} 

Обратите внимание, что только имена ключей/свойств должны быть строчными. Значения могут быть в верхнем регистре. Есть ли способ сделать JsonConvert.Deserializeobject чувствительным к регистру?

ответ

2

Вы можете написать собственный конвертер для обработки этого прецедента. Что касается вашей потребности в рекурсивной проверке всех ключевых имен, я использовал фантастический ответ WalkNode от Thyminehere.

var json = @"{""id"": ""id1"",""name"": ""name1"",""type"": ""type1""}"; 
var json2 = @"{""id"": ""id1"",""Name"": ""name1"",""type"": ""type1""}"; 

JsonSerializerSettings settings = new JsonSerializerSettings() 
{ 
    ContractResolver = new CamelCasePropertyNamesContractResolver(), 
    Converters = new List<JsonConverter> { new CamelCaseOnlyConverter() } 
}; 

var response = JsonConvert.DeserializeObject<Response>(json, settings); 
var response2 = JsonConvert.DeserializeObject<Response>(json2, settings); 

public class CamelCaseOnlyConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, 
     object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 

     var token = (JObject)JToken.Load(reader); 

     var isCamelCased = true; 
     WalkNode(token, null, 
     t => 
     { 
      var nameFirstChar = t.Name[0].ToString(); 
      if (!nameFirstChar.Equals(nameFirstChar.ToLower(), 
       StringComparison.CurrentCulture)) 
      { 
       isCamelCased = false; 
       return; 
      } 
     }); 

     if (!isCamelCased) return null; 

     return token.ToObject(objectType); 
    } 

    public override void WriteJson(JsonWriter writer, object value, 
     JsonSerializer serializer) 
    { 
     JObject o = (JObject)JToken.FromObject(value); 
     o.WriteTo(writer); 
    } 

    private static void WalkNode(JToken node, 
          Action<JObject> objectAction = null, 
          Action<JProperty> propertyAction = null) 
    { 
     if (node.Type == JTokenType.Object) 
     { 
      if (objectAction != null) objectAction((JObject)node); 
      foreach (JProperty child in node.Children<JProperty>()) 
      { 
       if (propertyAction != null) propertyAction(child); 
       WalkNode(child.Value, objectAction, propertyAction); 
      } 
     } 
     else if (node.Type == JTokenType.Array) 
      foreach (JToken child in node.Children()) 
       WalkNode(child, objectAction, propertyAction); 
    } 
} 

Первая строка вернет увлажненный объект. Вторая строка будет завершена раньше, возвращая значение null.

+0

@Romonov конечно предмет. Обновленный ответ будет правильно отклонять вторую строку. –

+0

Это прекрасно работает! – Romonov

+0

@ Ромонов потрясающий, рад помочь :) –

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