Deserializing JSON string fails when JSON dictionary is empty
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
|
show 4 more comments
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
means yourfood
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
|
show 4 more comments
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
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
c# json.net
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 yourfood
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
|
show 4 more comments
means yourfood
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
|
show 4 more comments
1 Answer
1
active
oldest
votes
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 ""
}
}
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 ""
}
}
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
add a comment |
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 ""
}
}
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
add a comment |
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 ""
}
}
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 ""
}
}
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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