Reputation: 131
I'm experiencing an issue with turning JSON into a string string dictionary. Here is a bit of the JSON text that I am trying to turn into a dictionary in C#.
{
"game": {
"players": {
"limit": "10000",
"ip_limit": "4"
}
}
}
Error while loading config. Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List
1[System.Collections.Generic.KeyValuePair
2[System.String,System.String]]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'database', line 2, position 15. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
_configItems = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(File.ReadAllText(fileName))
.ToDictionary(pair => pair.Key, pair => pair.Value);
_configItems is a Dictionary<string, string>
Upvotes: 0
Views: 1189
Reputation: 714
Just another info to add to @Waeschers answer, if you are not sure about how to get the classes, In visual studio, you can copy the json you want to deserialize and go to Edit --> PasteSpecial --> Paste Json as Classes. It will create create the same classes as @Waeschers mentioned.
Upvotes: 0
Reputation: 5737
You cannot deserialize a class with hierarchical properties to a list of keyvaluepairs. I assume you want to have a list of keyvaluepairs from these items:
key=limit : value=10000
--------------------------
key=ip_limit : value=4
But if so, what should your serializer do with the properties "game" and "players"? Just ignore it? How should it know what to ignore and what to deserialize?
So, you should try to bring the json content to a code structure, like a class for example. Of course you could write the classes manually but googling for "json to c# classes" could be a good idea here. Just form classes to match the json string so you can bring the json values into your code.
You might get something like this:
public class Game
{
public Players players { get; set; }
}
public class Players
{
public string limit { get; set; }
public string ip_limit { get; set; }
}
I bet that you could deserialize your data like this:
var game = JsonConvert.DeserializeObject<Game>(File.ReadAllText(fileName));
Once you have that, you can now access the property game.Players
and its sub properties limit
and ip_limit
.
Note that I would recommend to use clean propertynames here and map the values with json attributes.
Now that you got that - if you really still need a Dictionary for those values (you might not need to because you can easily access the values now) you can use the method ToDictionary()
on your game
object.
Upvotes: 4
Reputation: 14477
If you need to skip the root object and the first layer, you can simply use these:
var json = File.ReadAllText(fileName);
_configItems = JObject.Parse(json)["game"]["players"]
.Children<JProperty>()
.ToDictionary(x => x.Name, x => (string)x.Value);
However, do consider using @Waescher's approach of deserializing into a proper class if you can adjust the existing code to make it fit. But change the string
types into the what is more appropriate, like: int
.
Upvotes: 1