2

I have simple class:

public class TestObject {
    public string Label { get; set; } = string.Empty;
    public double Number { get; set; } = 0;
}

I would like to get an instance of TestObject from json. The trick is to allow Label and Number properties be optional, but throw exception if any extra field are added (to avoid mistake like "Lebel").

Code below alway convert to TestObject:

        var correctInput = $"{{\"Label\":\"a\", \"Number\":5 }}";
        var incorrectInput = $"{{\"Labell\":\"a\", \"Numberr\":5 }}";

        JToken obj1 = JsonConvert.DeserializeObject<dynamic>(correctInput);
        JToken obj2 = JsonConvert.DeserializeObject<dynamic>(incorrectInput);

        var correctResult = obj1.ToObject<TestObject>();
        var incorrectResult = obj2.ToObject<TestObject>();

        Console.WriteLine($"Label: {correctResult.Label} Number: {correctResult.Number}");
        Console.WriteLine($"Label: {incorrectResult.Label} Number: {incorrectResult.Number}");

The output of it will be:

Label: a Number: 5
Label:  Number: 0

Only solution which comes to my mind is to define extra field with property [JsonExtensionData] and throw exception to set accessor:

[JsonExtensionData]
private IDictionary<string, JToken> _extraStuff {
  get { return _extraStuff1; }
  set { throw new Exception("cannot do it");}
}

But it is quite ugly hack.

Grzegorz
  • 93
  • 8
  • 2
    Any reason you take the extra step of going to a JToken instead of just doing `JsonConvert.DeserializeObject(`? – Scott Chamberlain Jan 23 '18 at 21:44
  • In my case deserialize method has been already invoked. What I am doing is to get from JObject inner element which is JArray and parse it to specific object. That is why ToObject method is called – Grzegorz Jan 24 '18 at 11:48

1 Answers1

1

I think you need to set MissingMemberHandling = MissingMemberHandling.Error

In case Label property in JSON is misspeled as 'Labell'

var incorrectInput = $"{{\"Labell\":\"a\", \"Numberr\":5 }}";

JsonConvert.DeserializeObject<TestObject>(
   incorrectInput, 
   new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Error });

that will force to throw JsonSerializationException:

'Could not find member 'Labell' on object of type 'TestObject'.

Refer to the Newtonsoft docs for more information @ https://www.newtonsoft.com/json/help/html/DeserializeMissingMemberHandling.htm

pmcilreavy
  • 3,076
  • 2
  • 28
  • 37
koryakinp
  • 3,989
  • 6
  • 26
  • 56
  • Thanks. That was very helpful. For my case (calling ToObject method) it will be: `var correctResult = obj1.ToObject (JsonSerializer.Create(new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Error }));` – Grzegorz Jan 24 '18 at 11:51