Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JsonConvert DeserializeObject case sensitive [duplicate]

I am trying to deserialize a string content into an object, but I want the content to be case sensitive. The code should only succeed if the string has lower case properties and fail if it has upper case properties. Following is the class:

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

Following is the code I have. But this is not case-sensitive. It is succeeding for both upper and lowercase:

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

The code should only succeed if the content is:

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

and fail if even if one of the keys is uppercase. E.g.

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

Notice that only the Keys/Property names should be lower case. The values can be upper case. Is there a way to make JsonConvert.Deserializeobject case sensitive?

like image 831
Romonov Avatar asked Aug 03 '16 22:08

Romonov


People also ask

What exceptions does Jsonconvert Deserializeobject throw?

Serialization or deserialization errors will typically result in a JsonSerializationException .

Is JSON Net case sensitive?

JSON is case sensitive to both field names and data. So is N1QL. JSON can have the following.

Is Newtonsoft JSON deserialize case sensitive?

Case insensitive deserialization: By default, Newtonsoft. Json does case insensitive property name matching during deserialization whereas System. Text.

Is Newtonsoft case sensitive?

Newtonsoft uses case insensitive deserialization by default, so this is easy: using Newtonsoft.


1 Answers

You can write a custom converter to handle this use case. In regards to your need for a recursive inspection of all key names, I used the fantastic WalkNode answer given by Thymine here.

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

The first string will return a hydrated object. The second string will terminate early, returning null.

like image 103
David L Avatar answered Sep 17 '22 18:09

David L