Trying to convert JSON to [Key,Value] dictionary - c#

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"}

Related

How to convert json key value array to DTO in C# [duplicate]

I'm quite new to JSON, and am currently learning about (de)serialization.
I'm retrieving a JSON string from a webpage and trying to deserialize it into an object. Problem is, the root json key is static, but the underlying keys are dynamic and I cannot anticipate them to deserialize. Here is a mini example of the string :
{
"daily": {
"1337990400000": 443447,
"1338076800000": 444693,
"1338163200000": 452282,
"1338249600000": 462189,
"1338336000000": 466626
}
}
For another JSON string in my application, I was using a JavascriptSerializer and anticipating the keys using class structure. What's the best way to go about deserializing this string into an object?
Seriously, no need to go down the dynamic route; use
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
to get a dictionary, and then you can e.g.
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
to get the keys present and the corresponding values.
You can use dynamic in .NET 4 or later. For example with JSON.NET I can do:
dynamic obj = JsonConvert.Deserialize<dynamic>("{x: 'hello'}");
You can then do:
var str = obj.x;
However, unsure how it will handle numeric keys. You can of course just use JObject directly itself, for example:
var obj = JObject.Parse("{'123456': 'help'}");
var str = obj["123456"];
Whenever you have JSON with dynamic keys it can usually be deserialized into a Dictionary<string, SomeObject>. Since the inner JSON keys are dynamic (in this question) the JSON can be modelled as:
Dictionary<string, Dictionary<string, int>>
I would recommend using NewtonSoft.Json (JSON.Net) or System.Text.Json (if you're working in .NET-Core 3.0 and up).
Newtonsoft.Json
Use DeserializeObject<T> from JsonConvert:
var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);
System.Text.Json
Use Deserialize<T> from JsonSerializer:
var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);
This is not convenient to use, because in с# can not be defined a variable starts with a number. Add prefix to keys.
Or try this:
string json = "
{ daily:[
{ key: '1337990400000', val:443447 },
{ key: '1338076800000', val:444693 },
{ key: '1338163200000', val:452282 },
{ key: '1338249600000', val:462189 },
{ key: '1338336000000', val:466626 }]
}";
public class itemClass
{
public string key; // or int
public int val;
}
public class items
{
public itemClass[] daily;
}
items daily = (new JavascriptSerializer()).Deserialize<items>(json);
Then you can:
var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();

JSON.NET Array conversion

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"}
]

JSON array to C# Dictionary

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);

parsing JSON and removing extraneous characters before adding to observable collection

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],

Deserializing JSON with dynamic keys

I'm quite new to JSON, and am currently learning about (de)serialization.
I'm retrieving a JSON string from a webpage and trying to deserialize it into an object. Problem is, the root json key is static, but the underlying keys are dynamic and I cannot anticipate them to deserialize. Here is a mini example of the string :
{
"daily": {
"1337990400000": 443447,
"1338076800000": 444693,
"1338163200000": 452282,
"1338249600000": 462189,
"1338336000000": 466626
}
}
For another JSON string in my application, I was using a JavascriptSerializer and anticipating the keys using class structure. What's the best way to go about deserializing this string into an object?
Seriously, no need to go down the dynamic route; use
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
to get a dictionary, and then you can e.g.
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
to get the keys present and the corresponding values.
You can use dynamic in .NET 4 or later. For example with JSON.NET I can do:
dynamic obj = JsonConvert.Deserialize<dynamic>("{x: 'hello'}");
You can then do:
var str = obj.x;
However, unsure how it will handle numeric keys. You can of course just use JObject directly itself, for example:
var obj = JObject.Parse("{'123456': 'help'}");
var str = obj["123456"];
Whenever you have JSON with dynamic keys it can usually be deserialized into a Dictionary<string, SomeObject>. Since the inner JSON keys are dynamic (in this question) the JSON can be modelled as:
Dictionary<string, Dictionary<string, int>>
I would recommend using NewtonSoft.Json (JSON.Net) or System.Text.Json (if you're working in .NET-Core 3.0 and up).
Newtonsoft.Json
Use DeserializeObject<T> from JsonConvert:
var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);
System.Text.Json
Use Deserialize<T> from JsonSerializer:
var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);
This is not convenient to use, because in с# can not be defined a variable starts with a number. Add prefix to keys.
Or try this:
string json = "
{ daily:[
{ key: '1337990400000', val:443447 },
{ key: '1338076800000', val:444693 },
{ key: '1338163200000', val:452282 },
{ key: '1338249600000', val:462189 },
{ key: '1338336000000', val:466626 }]
}";
public class itemClass
{
public string key; // or int
public int val;
}
public class items
{
public itemClass[] daily;
}
items daily = (new JavascriptSerializer()).Deserialize<items>(json);
Then you can:
var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();

Categories