How do I deserialize JSON into a C# Dictionary? - c#

Problem
Heres my JSON object:
{
"1000":{
"id": "23445",
"latlon": "6780"
},
"1001":{
"id": "23454",
"latlon": "6784"
},
"1002":{
"id": "23245",
"latlon": "6180"
},
"1003":{
"id": "12345",
"latlon": "6740"
}
}
As you can see the property names are pure integers (1000, 1001, 1002, 1003)
I can't declare class variable names in integar and run System.json.Serialization.
Therefore I need to load the JSON file into:
public static Dictionary<int, NodeDetail> NodeInfo;
public class NodeDetail {
public ulong id;
public int latlon;
//Generic class serializer
//Generic class deserializer
}
Is there a library function for this? or do I have to parse the JSON string from ground up?
ps. I'm new to C#(coming from C++)

Newtonsoft.Json. You can pull it from NuGet.
Simple example:
public static T DeserializeJson<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
and then
Dictionary<string, object> foo = DeserializeJson<Dictionary<string, object>>(" ... insert JSON here ... ");
EDIT: given the structure you mention in your question, you may want to deserialize into a nested dictionary:
Dictionary<int, Dictionary<long, int>> foo = DeserializeJson<Dictionary<int, Dictionary<long, int>>>(" ... insert JSON here ...");
There's also JObject (in the same Newtonsoft.Json library) which is very helpful for deserializing to something uniform that can be used.

Related

c# system.text.json deserialize "different" object to an array of one class

I've a json that have objects like this
"SeasonalInfoBySeasonID": {
"aa8e0d2d-d29d-4c03-84f0-b0bda96a9fe1": {
"ID": "aa8e0d2d-d29d-4c03-84f0-b0bda96a9fe1",
"A": "1",
"B": 5,
},
"6f95fb92-5eb2-4fe4-ae01-dc54d810c8a5": {
"ID": "6f95fb92-5eb2-4fe4-ae01-dc54d810c8a5",
"A": "1",
"B": 5,
}, .....
}
the objects of SeasonalInfoBySeasonID are clearly all of the same data structure, but unfortunately they aren't even listed in an array, and instead of listing them one by one in seasoninfobyseasonid model I'm using doing this:
public class SeasonalInfoBySeasonID
{
private IDictionary<string, object> _additionalProperties = new Dictionary<string, object>();
[JsonExtensionData]
public IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties; }
set { _additionalProperties = value; }
}
}
works great, but I was wondering is it possible to de-serialize such an object with multiple objects of the "same type", to an array directly?
You don't need the class at all.
You can just declare the property on the root object like this
public Dictionary <string, YourType> SeasonalInfoBySeasonID {get;set;} = new Dictionary <string, YourType>();
Then each key will be aa8e0d2d-d29d-4c03-84f0-b0bda96a9fe1 etc., and the objects will be the inner type.

How to obtain a list of dynamic object keys/values from NewtonSoft Deserialised into Dynamic var

I have a C# class that receives a JSON string, and deserialises it into a dynamic.
json = #"{
"Id": "97dc4a96-43cf-48bd-9358-8f33e910594e",
"RepId": 90037,
"Something": true,
"SomethingElse": "abcdefg",
"Thing_1_of_MaybeDozens": 55
}";
dynamic jsonData = JsonConvert.DeserializeObject(json);
I can't deserialse into a class because while each JSON string will always have two known data elements (Id, and RepId), the rest of the string may have many elements that I do not know ahead of time their names, or how many of them there are.
I can always ask for jsonData.Id, or jsonData.RepId, but I do not know how many other elements there may be, nor how to refer to them.
I need something similar to JavaScript's Object.Keys(myObject).
Anyone knows how to do similar in C# with a Newtonsoft Deserialised JSON string?
You can use Reflection:
public Dictionary<string, object> DynamicToDictionary(dynamic obj)
{
var dict = new Dictionary<string, object>();
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(obj))
{
object obj2 = pd.GetValue(obj);
dict.Add(pd.Name, obj2);
}
return dict;
}
Now you may use the dictionary's TryGetValue(), and ContainsKey().
try to use Newtonsoft.Json extensions
var data = JsonConvert.DeserializeObject<Data>(json);
list of keys
List<string> additionalKeys=data.AdditionalData.Select(ad => ad.Key).ToList();
output
["Something","SomethingElse","Thing_1_of_MaybeDozens"]
how to use
var id = data.Id; //97dc4a96-43cf-48bd-9358-8f33e910594e
var somethingElse = data.AdditionalData["SomethingElse"]; // abcdefg
class
public class Data
{
// normal deserialization
public string Id { get; set; }
public long RepId { get; set; }
//additional data
[JsonExtensionData]
public Dictionary<string, object> AdditionalData {get;set;}
}

Object structure neccessary to serialize collection into arrays of JSON Objects

I want to use JSON.Net to serialize a complex C#.net object into JSON. The class structure is flexible (completely under my control), but JSON is needed in a specific format to communicate with another application. I require JSON in the following format, but need assistance composing the classes and nested collections:
{
"Record_1": [ { "key_1": "value_1", "key_N": "value_N"}, { "key_1": "value_1", "key_N": "value_N"}],
"Record_2": [ { "key_1": "value_1" } ],
"Record_N": [ { "key_1": "value_1" } , { "key_N":"value_N"}],
… Other properties (simple string key value pairs)
}
There will be 1 or more Record properties, the value of each Record is an array of objects.
The Record property names are not known (I have a list of possibilities, but do not want to hardcode them into the application).
There will be 1 or more objects in each array.
The objects in the array will have 1 or more string key value pairs. Again, property names are not known at compile time.
Since the Record properties were unknown, I tried using a dictionary of objects (Dictionary<string,object>) annotated with [JsonExtensionData]. The value object in the dictionary was another collection. However, that results in string properties with object values:
"Record_1": { key_1: [ value_1, value_2, value_N] }, "Record_N": { key_1: [value_1] }
Close, but not correct, the value of Record has to be an array.
Next, I tried using a list of lists of objects, but that didn't work either because the variable names of the lists are returned as the property names:
"RecordSet": [
{
"Records": [
{
"Key_1": "Value_1"
}
]
},
{
"Records": [
{
"Key_1": "Value_1",
}
]
}
]
So this does result in an array objects, but contents of the object are not in the correct form.
I believe I need some combination of nested collections in my class to output the records in the required JSON format, but I don't know which. Hopefully someone else has encountered this situation before.
BTW: Currently, I'm directly writing to the JSON object to get the structure required. I'm hoping that there will be some performance increase in refactoring for serialization. I'm not looking to just add complexity so I can say I'm following object oriented coding principles. There will never be a need for deserialization of this JSON back into an object.
Updated answer (see comments for why):
The structure to match your JSON is Dictionary<string, List<Dictionary<string, string>>>. You'll have to figure out how to fill the property names you want for the first Dictionary key. One suggestion for that is to have an interface, something like ICanSerializeToSpecificJSONFormat, and then have all your classes implement that interface, with a method to convert the desired properties into this structure.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace SomeNamespace
{
class Program
{
static void Main()
{
var d1 = new Dictionary<string, string>
{
{ "key_1", "value_1" }
};
var d2 = new Dictionary<string, string>(d1)
{
{ "key_2", "value_2" }
};
var objectToSerialize = new Dictionary<string, List<Dictionary<string, string>>>
{
{ "Record_1", new List<Dictionary<string, string>> { d1, d2 } },
{ "Record_2", new List<Dictionary<string, string>> { d1 } }
};
string recordsAsJson = JsonConvert.SerializeObject(objectToSerialize);
Console.WriteLine(recordsAsJson);
// prints:
// {"Record_1":[{"key_1":"value_1"},{"key_1":"value_1","key_2":"value_2"}],"Record_2":[{"key_1":"value_1"}]}
}
}
}
Original answer:
You were close. You tried Dictionary<> and List<List<>>, but you need List<Dictionary<>>. Here's a fully compiling example for you:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace SomeNamespace
{
class RecordSet
{
public List<Dictionary<string, string>> Record_1 { get; set; }
public List<Dictionary<string, string>> Record_2 { get; set; }
}
class Program
{
static void Main()
{
var d1 = new Dictionary<string, string>
{
{ "key_1", "value_1" }
};
var d2 = new Dictionary<string, string>(d1)
{
{ "key_2", "value_2" }
};
var records = new RecordSet
{
Record_1 = new List<Dictionary<string, string>> { d1, d2 },
Record_2 = new List<Dictionary<string, string>> { d1 }
};
string recordsAsJson = JsonConvert.SerializeObject(records);
Console.WriteLine(recordsAsJson);
// prints:
// {"Record_1":[{"key_1":"value_1"},{"key_1":"value_1","key_2":"value_2"}],"Record_2":[{"key_1":"value_1"}]}
}
}
}
Hopefully you can use this as a guide for creating your own RecordSet class (e.g. modifying to add the 'other properties' you mention).

JSON array to Dictionary

I'm trying to deserialize JSON to C# object using NewtonsoftJson.
My json looks like this:
{"something" : [ "key1" : "value1", "key2" : "value2"]}
But it's not a full json. So it should be kind of part of large object.
I can't use this solution JSON array to C# Dictionary
because I use
JsonConvert.DeserializeObject<MyObject>(json);
Does it possible to initialize object like this?
public class Something
{
[JsonProperty]
public Dictionary<string, string> MyDictionary;
}
But when I'm trying to do that I get exception:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,ConsoleApp4.TxPerfMeasurements]'
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.
Input
{
"something": [
{ "key1": "value1" },
{ "key2": "value2" }
]
}
Your model should look like below
public class Something
{
public List<Dictionary<string, string>> something { get; set; }
}
Use Linq to convert to Dictionary
var result = JsonConvert.DeserializeObject<Something>(json);
var dict = result.something.SelectMany(d => d).ToDictionary(e => e.Key, e => e.Value);
Output

Unable to Serialize JSON to Dictionary

I have an issue with JSON serialization into a class with a dictionary property.
The whole process is a bit more complex, as an input i have a YAML file that i convert into a json using YamlDotNet and NewtonSoft like so
This is an example of the Yaml and the JSON output
some_element: '1'
should_be_dic_element:
- a: '1'
- b: '2'
{
"some_element": "1",
"should_be_dic_element": [
{
"a": "1"
},
{
"b": "2"
}
]
}
And the class
public class SomeClass
{
[JsonProperty(PropertyName = "some_element")]
public string SomeProperty { get; set; }
[JsonProperty(PropertyName = "should_be_dic_element")]
public Dictionary<string, string> Dictionary { get; set; }
}
I know the issue with Array dictionary so this are all the things I've tried.
Using Dictionary i get the following
error 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
Using a new class from Dictionary like so
[JsonArray]
class X : Dictionary<string, string> { }
error Value cannot be null.
Parameter name: key
Using KeyValuePair<string, string>[] / List<KeyValuePair<string, string>> the outcome is the amount of elements but with null values.
Any suggestions please ?
I think your JSON which you are attempting to de-serialize is not conforming to your class definition. Try changing the way you are generating the JSON.
For a dictionary-type structure, I would expect to see curly braces { instead of [ to begin the structure, e.g.:
{
"some_element": "1",
"should_be_dic_element": {
{
"a": "1"
},
{
"b": "2"
}
}
}
If you want to deserialize the existing JSON unchanged, try using your class definition to specify a list of dictionaries as such:
public class SomeClass
{
[JsonProperty(PropertyName = "some_element")]
public string SomeProperty { get; set; }
[JsonProperty(PropertyName = "should_be_dic_element")]
public List<Dictionary<string, string>> Dictionary { get; set; }
}

Categories

Resources