I am writing some classes to make calls to an API that I did not write. The API was written sort of strangely and has some data that looks like this:
[
{
"AB": 20
},
{
"CD": 15
}
]
I know a typical Dictionary would serialize like so:
{
"AB": 20,
"CD": 15
}
Is there anything that I can map to to match what they have written without having to write a bunch of custom code?
One way to parse such a JSON and get a Dictionary containing all key/values is the following:
string json = #"
[
{
""AB"": 20
},
{
""CD"": 15
},
{
""EF"": 35
}
]";
JArray obj = JsonConvert.DeserializeObject<JArray>(json);
var dict = obj.ToList()
.SelectMany(x => x.ToList())
.Cast<JProperty>()
.ToDictionary(x => x.Name, x => x.Value);
Basically, it flattens all array elements and constructs a dictionary out of each element.
Related
I am trying to convert a JSON array to a C# dictionary.
My Box class has "id" and "color" properties.
{
"boxes" [
{"id":0, "color":"red"},
{"id":1, "color":"green"},
{"id":2, "color":"blue"}
]
}
I've tried a few things, but haven't had any luck getting this to work yet.
List<Box> jsonResponse = JsonConvert.DeserializeObject<List<Box>>(File.ReadAllText(filePath));
Well the thing is that your Dictionary is in nested property.
And even more - it's not really a dictionary. It is an array of objects where each object consists of two fields - id and color (whereas in dictionary we have key-value pairs).
You could deserialize your json into anonymous object with correct structure and then get the array of boxes out of it and convert it to dictionary:
var box = new { id = 0, name = "" };
var jsonObj = new { boxes = new[] { box } };
var dict = JsonConvert.DeserializeAnonymousType(myJson, jsonObj).boxes
.ToDictionary(b => b.id, b => b.name);
JSON doesn't need {} at the top level - so you can just have your list of items in {}'s surrounded by [].
[
{"id":0, "color":"red"},
{"id":1, "color":"green"},
{"id":2, "color":"blue"}
]
I have some JSON that looks like this:
{
"innerObj1": {
"1. Information": "unimportant"
},
"innerObj2": {
"2017-09-19 16:00:00": {
"number1": "75.4500"
},
"2017-09-19 15:55:00": {
"number2": "75.4200"
}
}
}
Not sure why innerObj2 is not returned as an array (this is from an api) but I have to get number1 and number2 returned as an array of strings. Note that 2017-09-19 16:00:00 and 2017-09-19 15:55:00 are subject to change, so I can't hardcode the selection of those objects in C#. I was thinking of possibly using LINQ, but I'm not sure how. I've really only used them with JSON arrays.
Assuming you are using Json.Net, you can get the values of the innermost properties into an array like this, without needing to know the names of them:
JObject obj = JObject.Parse(json);
string[] numbers = ((JObject)obj["innerObj2"]).Properties()
.SelectMany(jp => ((JObject)jp.Value).Properties())
.Select(jp => (string)jp.Value)
.ToArray();
Fiddle: https://dotnetfiddle.net/5sLy6M
Or, a simpler alternative which does the same thing using SelectTokens with a JSONPath wildcard expression:
string[] numbers = obj.SelectTokens("innerObj2.*.*")
.Select(jt => (string)jt)
.ToArray();
Fiddle: https://dotnetfiddle.net/CyRQ9T
How do I convert a JSON array like this
[{"myKey":"myValue"},
{"anotherKey":"anotherValue"}]
to a C# Dictionary with json.net or system classes.
json.net can serialize directly to a dictionary, but only if you feed it an object, not an array.
Maybe converting to array of KeyValuePairs will help
using System.Linq;
var list = JsonConvert.DeserializeObject<IEnumerable<KeyValuePair<string, string>>>(jsonContent);
var dictionary = list.ToDictionary(x => x.Key, x => x.Value);
For anyone interested - this works, too:
Example JSON:
[{"device_id":"VC2","command":6,"command_args":"test args10"},
{"device_id":"VC2","command":3,"command_args":"test args9"}]
C#:
JsonConvert.DeserializeObject<List<JObject>>(json)
.Select(x => x?.ToObject<Dictionary<string, string>>())
.ToList()
Its quite simple actually :
lets say you get your json in a string like :
string jsonString = #"[{"myKey":"myValue"},
{"anotherKey":"anotherValue"}]";
then you can deserialize it using JSON.NET as follows:
JArray a = JArray.Parse(jsonString);
// dictionary hold the key-value pairs now
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (JObject o in a.Children<JObject>())
{
foreach (JProperty p in o.Properties())
{
string name = p.Name;
string value = (string)p.Value;
dict.Add(name,value);
}
}
I found that using a list of KeyValuePairs didn't work. I got the right number of elements but they had null Keys and Values.
In the end the only solution that worked for me was deserialising to a list of dictionaries (which each had a single kvp element).
The data must to be sent as follows (format):
"Values": [
{"Key" : "abc" , "Value": 23.14},
{"Key" : "abc1" , "Value": 23.11},
{"Key" : "abc2" , "Value": 23.17},
{"Key" : "abc3" , "Value": 23.19}
]
thereby, the converting process will work. It worked fine to me in my attempt to convert from JSON to dictionary<string,decimal>
Since you can only deserialize from an object, do just that by manipulating the JSON string a little first. Wrap it in an object:
json = String.Format("{{\"result\":{0}}}", json);
I'm using Newtonsoft.Json any trying to convert JSON to Dictionary<string,string>
This is the JSON file:
[
{
"<p dir=\"rtl\">":""
},
{
"<p>":""
},
{
"<p dir='rtl'>":""
},
{
"<div dir='rtl'>":""
},
{
"<div>":""
},
{
"<div dir=\"rtl\">":""
},
{
"<script>":"<script>"/
},
{
"</script>":"</script>"
},
{
"<button>":"<button>"
},
{
"<button":"<button"
},
{
"</button>":"</button>"
},
{
"<br>":"<br>"
},
{
"<br />":"<br>"
},
{
"<br/>":"<br>"
},
{
"</br>":"<br>"
},
{
"\"":""
}
]
And this is the code:
var replaceTags = System.IO.File.ReadAllText(JSON_FILE_PATH);
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(replaceTags);
And I'm got the following exception:
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 '', line 1, position 1.
Why Its happend?
Thanks!
Like I said in the comments, your JSON isn't a dictionary, but rather an array of dictionaries. You can merge them all into a single dictionary like so:
string input = File.ReadAllText("file.json");
var jsonObj = JsonConvert.DeserializeObject<Dictionary<string, string>[]>(input);
var dict = jsonObj.SelectMany(d => d)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
However, because of the way the JSON is structured, there's not going to be any guarantee that there won't be duplicate keys. To prevent this, you could also filter any potential duplicates out:
var dict = jsonObj.SelectMany(d => d)
.GroupBy(kvp => kvp.Key)
.Select(g => g.First())
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
In my opinion, though, unless there is a very good reason that you absolutely need to serialize this JSON into a single Dictionary, you should just leave it as an array of dictionaries (since that's what it is):
string input = File.ReadAllText("file.json");
var dictArray = JsonConvert.DeserializeObject<Dictionary<string, string>[]>(input);
Here is a simple example of serializing a dictionary of string,string to a JSON text. Your text will obviously come from your file path once read.
var myd = new Dictionary<string, string>();
myd.Add("1","A");
myd.Add("2", "B");
var dText = JsonConvert.SerializeObject(myd);
This gives you the below string.
{"1":"A","2":"B"}
This will then deserialize back to a dictionary.
var restoredDictionary = JsonConvert.DeserializeObject<Dictionary<string,string>>(dText);
Suggest you reverse engineer this. Manually create a dictionary with the data you are expecting. Serialize it and see what the file contents should be.
You may find that whatever is generating the source file in "JSON_FILE_PATH" is the source of your problem.
You're JSON isn't right, for a dictionary of type string,string. Try changing the format to match:
{"key1":"value1","key2":"value2"}
I am trying to GET JSON From a webservice , which i was able to figure out . BTW This was my JSON Data
{
"X-YZ-111/AB.CD": {
"P1": "F",
"P2": "43.46"
},
"X-YZ-112/AB.CDRTE.D": {
"P1": "F",
"P2": "8.02"
}
}
Now i am able trying to parse it into a collection,where each item has "X-YZ-111/AB.CD" as name property and P1 and P2 as other 2 properties ,which i will try to bind to a Tile in UI using CollectionViewSource later.
I am able to parse the JSON into my classes like this -
var jObj = JObject.Parse(result);
var dict = jObj.Children()
.Cast<JProperty>()
.ToDictionary(p => p.Name,
p => new Tuple<string, string>((string)p.Value["P1"], (string)p.Value["P2"]));
But after parsing JSON and before adding the dict collection to observable collection i want to strip off all characters after "/" from Name Property.
So if it is "X-YZ-112/AB.CDRTE.D" , i want Name to be "X-YZ-112" and strip off "AB.CDRTE.D". My Json data has 21 objects like this and all object's Name have this extraneous data. Is there anyway i can strip these chars before adding them to my observable collection?
How about creating a new dictionary?
var newDict = dict.ToDictionary(kv => kv.Key.Split('/')[0], kv => kv.Value);
You also can do the same thing while parsing your json.
p => p.Name.Split('/')[0],