Deserializing JSON string fails when JSON dictionary is empty












0















Currently I'm facing the following issue when I try to deserialize a json string that I receive from a 3rd party (--> I cannot change the received json string by myself) with Newtonsoft.Json:



The json contains a dictionary (and some other entries that I don't list here):



"food": {
"Menu 1": "abc",
"Menu 2": "def"
}


I've created a class that contains the property (plus the properties that I didn't list here):



Dictionary<string, string> Food {get; set;}


In this case the desiralization of the json works fine.
The problem occurs when food is empty:



{
"food": ,
}


In this case it seems that food is not a dictionary but an array.
That's the reason why the desirialization fails with the following error:




Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,System.String]'
because the type requires a JSON object (e.g. {"name":"value"}) to
deserialize correctly. To fix this error either change the JSON to a
JSON object (e.g. {"name":"value"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array. Path 'food'."




Is anybody out there who can help me to solve this problem, please?



EDIT
The desiralization code:



public T DeserializeAPIResults<T>(string json)
{
JObject obj = JsonConvert.DeserializeObject<JObject>(json);
return obj.GetValue("canteen").ToObject<T>();
}


EDIT 2
Full json with values:



        {
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi",
"Menu 4": "jkl",
"Menu 5": "mno"
}
},
{
"name": "Canteen2",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi"
}
},
{
"name": "Canteen3",
"src": "a link",
"food": {
"Line 1": "abc",
"Line 2": "def",
"Line 3": "ghi"
}
}
]
}


Full json without values:



{
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": ,
},
{
"name": "Canteen2",
"src": "a link",
"food": ,
},
{
"name": "Canteen3",
"src": "a link",
"food": ,
}
]
}


EDIT 3
The class:



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("food")]
public Dictionary<string, string> Food { get; set; }
public Canteen() { }
}


And the method call:



Canteen canteens = DeserializeAPIResults<Canteen>(json);









share|improve this question

























  • means your food key contains sometime object and sometime array right?

    – er-sho
    Nov 24 '18 at 13:04













  • It seems like. When food is not empty it is always a dictionary. Only when it is empty it is treated as an array.

    – M. Mustermann
    Nov 24 '18 at 13:06











  • show me your deserialization code?

    – er-sho
    Nov 24 '18 at 13:08











  • I've added the deserialization code

    – M. Mustermann
    Nov 24 '18 at 13:14











  • @er-shoaib - he is saying when food is empty it returns like empty array but when its not empty its dictionary.

    – Mayur Lohite
    Nov 24 '18 at 13:16
















0















Currently I'm facing the following issue when I try to deserialize a json string that I receive from a 3rd party (--> I cannot change the received json string by myself) with Newtonsoft.Json:



The json contains a dictionary (and some other entries that I don't list here):



"food": {
"Menu 1": "abc",
"Menu 2": "def"
}


I've created a class that contains the property (plus the properties that I didn't list here):



Dictionary<string, string> Food {get; set;}


In this case the desiralization of the json works fine.
The problem occurs when food is empty:



{
"food": ,
}


In this case it seems that food is not a dictionary but an array.
That's the reason why the desirialization fails with the following error:




Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,System.String]'
because the type requires a JSON object (e.g. {"name":"value"}) to
deserialize correctly. To fix this error either change the JSON to a
JSON object (e.g. {"name":"value"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array. Path 'food'."




Is anybody out there who can help me to solve this problem, please?



EDIT
The desiralization code:



public T DeserializeAPIResults<T>(string json)
{
JObject obj = JsonConvert.DeserializeObject<JObject>(json);
return obj.GetValue("canteen").ToObject<T>();
}


EDIT 2
Full json with values:



        {
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi",
"Menu 4": "jkl",
"Menu 5": "mno"
}
},
{
"name": "Canteen2",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi"
}
},
{
"name": "Canteen3",
"src": "a link",
"food": {
"Line 1": "abc",
"Line 2": "def",
"Line 3": "ghi"
}
}
]
}


Full json without values:



{
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": ,
},
{
"name": "Canteen2",
"src": "a link",
"food": ,
},
{
"name": "Canteen3",
"src": "a link",
"food": ,
}
]
}


EDIT 3
The class:



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("food")]
public Dictionary<string, string> Food { get; set; }
public Canteen() { }
}


And the method call:



Canteen canteens = DeserializeAPIResults<Canteen>(json);









share|improve this question

























  • means your food key contains sometime object and sometime array right?

    – er-sho
    Nov 24 '18 at 13:04













  • It seems like. When food is not empty it is always a dictionary. Only when it is empty it is treated as an array.

    – M. Mustermann
    Nov 24 '18 at 13:06











  • show me your deserialization code?

    – er-sho
    Nov 24 '18 at 13:08











  • I've added the deserialization code

    – M. Mustermann
    Nov 24 '18 at 13:14











  • @er-shoaib - he is saying when food is empty it returns like empty array but when its not empty its dictionary.

    – Mayur Lohite
    Nov 24 '18 at 13:16














0












0








0


1






Currently I'm facing the following issue when I try to deserialize a json string that I receive from a 3rd party (--> I cannot change the received json string by myself) with Newtonsoft.Json:



The json contains a dictionary (and some other entries that I don't list here):



"food": {
"Menu 1": "abc",
"Menu 2": "def"
}


I've created a class that contains the property (plus the properties that I didn't list here):



Dictionary<string, string> Food {get; set;}


In this case the desiralization of the json works fine.
The problem occurs when food is empty:



{
"food": ,
}


In this case it seems that food is not a dictionary but an array.
That's the reason why the desirialization fails with the following error:




Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,System.String]'
because the type requires a JSON object (e.g. {"name":"value"}) to
deserialize correctly. To fix this error either change the JSON to a
JSON object (e.g. {"name":"value"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array. Path 'food'."




Is anybody out there who can help me to solve this problem, please?



EDIT
The desiralization code:



public T DeserializeAPIResults<T>(string json)
{
JObject obj = JsonConvert.DeserializeObject<JObject>(json);
return obj.GetValue("canteen").ToObject<T>();
}


EDIT 2
Full json with values:



        {
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi",
"Menu 4": "jkl",
"Menu 5": "mno"
}
},
{
"name": "Canteen2",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi"
}
},
{
"name": "Canteen3",
"src": "a link",
"food": {
"Line 1": "abc",
"Line 2": "def",
"Line 3": "ghi"
}
}
]
}


Full json without values:



{
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": ,
},
{
"name": "Canteen2",
"src": "a link",
"food": ,
},
{
"name": "Canteen3",
"src": "a link",
"food": ,
}
]
}


EDIT 3
The class:



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("food")]
public Dictionary<string, string> Food { get; set; }
public Canteen() { }
}


And the method call:



Canteen canteens = DeserializeAPIResults<Canteen>(json);









share|improve this question
















Currently I'm facing the following issue when I try to deserialize a json string that I receive from a 3rd party (--> I cannot change the received json string by myself) with Newtonsoft.Json:



The json contains a dictionary (and some other entries that I don't list here):



"food": {
"Menu 1": "abc",
"Menu 2": "def"
}


I've created a class that contains the property (plus the properties that I didn't list here):



Dictionary<string, string> Food {get; set;}


In this case the desiralization of the json works fine.
The problem occurs when food is empty:



{
"food": ,
}


In this case it seems that food is not a dictionary but an array.
That's the reason why the desirialization fails with the following error:




Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,System.String]'
because the type requires a JSON object (e.g. {"name":"value"}) to
deserialize correctly. To fix this error either change the JSON to a
JSON object (e.g. {"name":"value"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array. Path 'food'."




Is anybody out there who can help me to solve this problem, please?



EDIT
The desiralization code:



public T DeserializeAPIResults<T>(string json)
{
JObject obj = JsonConvert.DeserializeObject<JObject>(json);
return obj.GetValue("canteen").ToObject<T>();
}


EDIT 2
Full json with values:



        {
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi",
"Menu 4": "jkl",
"Menu 5": "mno"
}
},
{
"name": "Canteen2",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi"
}
},
{
"name": "Canteen3",
"src": "a link",
"food": {
"Line 1": "abc",
"Line 2": "def",
"Line 3": "ghi"
}
}
]
}


Full json without values:



{
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": ,
},
{
"name": "Canteen2",
"src": "a link",
"food": ,
},
{
"name": "Canteen3",
"src": "a link",
"food": ,
}
]
}


EDIT 3
The class:



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("food")]
public Dictionary<string, string> Food { get; set; }
public Canteen() { }
}


And the method call:



Canteen canteens = DeserializeAPIResults<Canteen>(json);






c# json.net






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 24 '18 at 15:46









Uwe Keim

27.6k32132212




27.6k32132212










asked Nov 24 '18 at 13:01









M. MustermannM. Mustermann

156




156













  • means your food key contains sometime object and sometime array right?

    – er-sho
    Nov 24 '18 at 13:04













  • It seems like. When food is not empty it is always a dictionary. Only when it is empty it is treated as an array.

    – M. Mustermann
    Nov 24 '18 at 13:06











  • show me your deserialization code?

    – er-sho
    Nov 24 '18 at 13:08











  • I've added the deserialization code

    – M. Mustermann
    Nov 24 '18 at 13:14











  • @er-shoaib - he is saying when food is empty it returns like empty array but when its not empty its dictionary.

    – Mayur Lohite
    Nov 24 '18 at 13:16



















  • means your food key contains sometime object and sometime array right?

    – er-sho
    Nov 24 '18 at 13:04













  • It seems like. When food is not empty it is always a dictionary. Only when it is empty it is treated as an array.

    – M. Mustermann
    Nov 24 '18 at 13:06











  • show me your deserialization code?

    – er-sho
    Nov 24 '18 at 13:08











  • I've added the deserialization code

    – M. Mustermann
    Nov 24 '18 at 13:14











  • @er-shoaib - he is saying when food is empty it returns like empty array but when its not empty its dictionary.

    – Mayur Lohite
    Nov 24 '18 at 13:16

















means your food key contains sometime object and sometime array right?

– er-sho
Nov 24 '18 at 13:04







means your food key contains sometime object and sometime array right?

– er-sho
Nov 24 '18 at 13:04















It seems like. When food is not empty it is always a dictionary. Only when it is empty it is treated as an array.

– M. Mustermann
Nov 24 '18 at 13:06





It seems like. When food is not empty it is always a dictionary. Only when it is empty it is treated as an array.

– M. Mustermann
Nov 24 '18 at 13:06













show me your deserialization code?

– er-sho
Nov 24 '18 at 13:08





show me your deserialization code?

– er-sho
Nov 24 '18 at 13:08













I've added the deserialization code

– M. Mustermann
Nov 24 '18 at 13:14





I've added the deserialization code

– M. Mustermann
Nov 24 '18 at 13:14













@er-shoaib - he is saying when food is empty it returns like empty array but when its not empty its dictionary.

– Mayur Lohite
Nov 24 '18 at 13:16





@er-shoaib - he is saying when food is empty it returns like empty array but when its not empty its dictionary.

– Mayur Lohite
Nov 24 '18 at 13:16












1 Answer
1






active

oldest

votes


















1














If your value for particular key are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData]. Read more




Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.




When your 3rd party json have an key with name food and its value as object then you are trying to deserialze into Dictionary<string, string> Food {get; set;} and your deserilization method correctly deserialize your json.



But when food key have array then your method fails to deserialize because you are trying to deserialize array into string.



If you use



[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }


Instead of



Dictionary<string, string> Food {get; set;}


Then your deserialization works.



So finally your class will be



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
public Canteen() { }
}




Alternative:



If you declare your Food property data type to JToken in your Canteen class like



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonProperty("food")]
public JToken Food { get; set; }

public Canteen() { }
}


Then you can successfully deserialize your json whether your food key is either object or array.



And then you can access your each of canteen from canteens array and retrieve each canteen's name, src and food key/value pair like.



The advantage of JToken is that you can check it's type whether its object or array



Canteen canteens = DeserializeAPIResults<Canteen>(json);

foreach (var canteen in canteens)
{
string name = canteen.Name;
string src = canteen.Src;
JToken food = canteen.Food;

if (food.Type == JTokenType.Object)
{
Dictionary<string, string> foods = food.ToObject<Dictionary<string, string>>();
}
else if (food.Type == JTokenType.Array)
{
//Do something if "foods" is empty array ""
}
}





share|improve this answer


























  • Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

    – M. Mustermann
    Nov 24 '18 at 14:14













  • Glad to hear, and i also have same question about that. Anyways welcomes yours :)

    – er-sho
    Nov 24 '18 at 14:22











  • I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

    – er-sho
    Nov 24 '18 at 15:31













  • Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

    – M. Mustermann
    Nov 24 '18 at 20:42











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53458399%2fdeserializing-json-string-fails-when-json-dictionary-is-empty%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














If your value for particular key are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData]. Read more




Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.




When your 3rd party json have an key with name food and its value as object then you are trying to deserialze into Dictionary<string, string> Food {get; set;} and your deserilization method correctly deserialize your json.



But when food key have array then your method fails to deserialize because you are trying to deserialize array into string.



If you use



[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }


Instead of



Dictionary<string, string> Food {get; set;}


Then your deserialization works.



So finally your class will be



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
public Canteen() { }
}




Alternative:



If you declare your Food property data type to JToken in your Canteen class like



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonProperty("food")]
public JToken Food { get; set; }

public Canteen() { }
}


Then you can successfully deserialize your json whether your food key is either object or array.



And then you can access your each of canteen from canteens array and retrieve each canteen's name, src and food key/value pair like.



The advantage of JToken is that you can check it's type whether its object or array



Canteen canteens = DeserializeAPIResults<Canteen>(json);

foreach (var canteen in canteens)
{
string name = canteen.Name;
string src = canteen.Src;
JToken food = canteen.Food;

if (food.Type == JTokenType.Object)
{
Dictionary<string, string> foods = food.ToObject<Dictionary<string, string>>();
}
else if (food.Type == JTokenType.Array)
{
//Do something if "foods" is empty array ""
}
}





share|improve this answer


























  • Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

    – M. Mustermann
    Nov 24 '18 at 14:14













  • Glad to hear, and i also have same question about that. Anyways welcomes yours :)

    – er-sho
    Nov 24 '18 at 14:22











  • I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

    – er-sho
    Nov 24 '18 at 15:31













  • Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

    – M. Mustermann
    Nov 24 '18 at 20:42
















1














If your value for particular key are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData]. Read more




Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.




When your 3rd party json have an key with name food and its value as object then you are trying to deserialze into Dictionary<string, string> Food {get; set;} and your deserilization method correctly deserialize your json.



But when food key have array then your method fails to deserialize because you are trying to deserialize array into string.



If you use



[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }


Instead of



Dictionary<string, string> Food {get; set;}


Then your deserialization works.



So finally your class will be



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
public Canteen() { }
}




Alternative:



If you declare your Food property data type to JToken in your Canteen class like



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonProperty("food")]
public JToken Food { get; set; }

public Canteen() { }
}


Then you can successfully deserialize your json whether your food key is either object or array.



And then you can access your each of canteen from canteens array and retrieve each canteen's name, src and food key/value pair like.



The advantage of JToken is that you can check it's type whether its object or array



Canteen canteens = DeserializeAPIResults<Canteen>(json);

foreach (var canteen in canteens)
{
string name = canteen.Name;
string src = canteen.Src;
JToken food = canteen.Food;

if (food.Type == JTokenType.Object)
{
Dictionary<string, string> foods = food.ToObject<Dictionary<string, string>>();
}
else if (food.Type == JTokenType.Array)
{
//Do something if "foods" is empty array ""
}
}





share|improve this answer


























  • Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

    – M. Mustermann
    Nov 24 '18 at 14:14













  • Glad to hear, and i also have same question about that. Anyways welcomes yours :)

    – er-sho
    Nov 24 '18 at 14:22











  • I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

    – er-sho
    Nov 24 '18 at 15:31













  • Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

    – M. Mustermann
    Nov 24 '18 at 20:42














1












1








1







If your value for particular key are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData]. Read more




Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.




When your 3rd party json have an key with name food and its value as object then you are trying to deserialze into Dictionary<string, string> Food {get; set;} and your deserilization method correctly deserialize your json.



But when food key have array then your method fails to deserialize because you are trying to deserialize array into string.



If you use



[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }


Instead of



Dictionary<string, string> Food {get; set;}


Then your deserialization works.



So finally your class will be



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
public Canteen() { }
}




Alternative:



If you declare your Food property data type to JToken in your Canteen class like



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonProperty("food")]
public JToken Food { get; set; }

public Canteen() { }
}


Then you can successfully deserialize your json whether your food key is either object or array.



And then you can access your each of canteen from canteens array and retrieve each canteen's name, src and food key/value pair like.



The advantage of JToken is that you can check it's type whether its object or array



Canteen canteens = DeserializeAPIResults<Canteen>(json);

foreach (var canteen in canteens)
{
string name = canteen.Name;
string src = canteen.Src;
JToken food = canteen.Food;

if (food.Type == JTokenType.Object)
{
Dictionary<string, string> foods = food.ToObject<Dictionary<string, string>>();
}
else if (food.Type == JTokenType.Array)
{
//Do something if "foods" is empty array ""
}
}





share|improve this answer















If your value for particular key are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData]. Read more




Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.




When your 3rd party json have an key with name food and its value as object then you are trying to deserialze into Dictionary<string, string> Food {get; set;} and your deserilization method correctly deserialize your json.



But when food key have array then your method fails to deserialize because you are trying to deserialize array into string.



If you use



[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }


Instead of



Dictionary<string, string> Food {get; set;}


Then your deserialization works.



So finally your class will be



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
public Canteen() { }
}




Alternative:



If you declare your Food property data type to JToken in your Canteen class like



public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }

[JsonProperty("food")]
public JToken Food { get; set; }

public Canteen() { }
}


Then you can successfully deserialize your json whether your food key is either object or array.



And then you can access your each of canteen from canteens array and retrieve each canteen's name, src and food key/value pair like.



The advantage of JToken is that you can check it's type whether its object or array



Canteen canteens = DeserializeAPIResults<Canteen>(json);

foreach (var canteen in canteens)
{
string name = canteen.Name;
string src = canteen.Src;
JToken food = canteen.Food;

if (food.Type == JTokenType.Object)
{
Dictionary<string, string> foods = food.ToObject<Dictionary<string, string>>();
}
else if (food.Type == JTokenType.Array)
{
//Do something if "foods" is empty array ""
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 24 '18 at 15:44

























answered Nov 24 '18 at 13:50









er-shoer-sho

6,3472617




6,3472617













  • Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

    – M. Mustermann
    Nov 24 '18 at 14:14













  • Glad to hear, and i also have same question about that. Anyways welcomes yours :)

    – er-sho
    Nov 24 '18 at 14:22











  • I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

    – er-sho
    Nov 24 '18 at 15:31













  • Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

    – M. Mustermann
    Nov 24 '18 at 20:42



















  • Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

    – M. Mustermann
    Nov 24 '18 at 14:14













  • Glad to hear, and i also have same question about that. Anyways welcomes yours :)

    – er-sho
    Nov 24 '18 at 14:22











  • I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

    – er-sho
    Nov 24 '18 at 15:31













  • Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

    – M. Mustermann
    Nov 24 '18 at 20:42

















Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

– M. Mustermann
Nov 24 '18 at 14:14







Thank you very much! I just tried your solution and it worked well for me. I have not seen the feature [JsonExtensionData] before. The only thing I ask myself is why the 3rd party does that. Why can't they just return a blank dictionary instead of an array if there's no data?

– M. Mustermann
Nov 24 '18 at 14:14















Glad to hear, and i also have same question about that. Anyways welcomes yours :)

– er-sho
Nov 24 '18 at 14:22





Glad to hear, and i also have same question about that. Anyways welcomes yours :)

– er-sho
Nov 24 '18 at 14:22













I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

– er-sho
Nov 24 '18 at 15:31







I've also added alternative to [JsonExtensionData]. kindly view Alternative section in answer :)

– er-sho
Nov 24 '18 at 15:31















Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

– M. Mustermann
Nov 24 '18 at 20:42





Thank you for your second solution to this problem. I think I will use this because it seems a little more useful to my approach. Anyway, the first version is good too :)

– M. Mustermann
Nov 24 '18 at 20:42




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53458399%2fdeserializing-json-string-fails-when-json-dictionary-is-empty%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen