2016-08-03 35 views
2

Ich versuche, einen String-Inhalt in ein Objekt zu deserialisieren, aber ich möchte den Inhalt Groß-und Kleinschreibung beachten. Der Code sollte nur dann erfolgreich sein, wenn die Zeichenfolge Kleinbuchstaben aufweist und bei Großbuchstaben fehlschlägt. Folgendes ist die Klasse:JsonConvert DeserializeObject case sensitive

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

Folgendes ist der Code, den ich habe. Aber dies ist nicht Groß-und Kleinschreibung. sowohl Groß- und Klein Es ist für den Erfolg:

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

Der Code sollte nur gelingen, wenn der Inhalt:

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

und fehlschlagen, wenn selbst wenn eine der Tasten Großbuchstaben ist. Z.B.

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

Beachten Sie, dass nur die Keys/Property-Namen Kleinbuchstaben sein sollten. Die Werte können Großbuchstaben sein. Gibt es eine Möglichkeit, JsonConvert.Deserializeobject case sensitive zu machen?

Antwort

2

Sie können einen benutzerdefinierten Konverter für diesen Anwendungsfall schreiben. In Bezug auf Ihre Notwendigkeit für eine rekursive Inspektion aller Schlüsselnamen, habe ich die fantastische WalkNode Antwort gegeben durch Thyminehere verwendet.

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

Die erste Zeichenfolge gibt ein hydriertes Objekt zurück. Die zweite Zeichenfolge wird vorzeitig beendet und gibt null zurück.

+0

@Romonov sicher Ding. Die aktualisierte Antwort wird die zweite Zeichenfolge ordnungsgemäß zurückweisen. –

+0

Das funktioniert perfekt! – Romonov

+0

@Romonov genial, glücklich zu helfen :) –