parsing JSON and removing extraneous characters before adding to observable collection - c#

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

Related

How to get the names of all properties (without their values) in a json object?

I have a json object, a string, that contains some properties and their values. Say I never know what comes in my json object, how can I loop though it and get what properties it contains? For example:
{
"aaaa": 1,
"bbbb": "qwerty",
"ccc": 21.22
}
How do I collect aaa, bbb and ccc? Once again, I don't want their values, I just want the name of the properties.
It's as simple as this:
var json = #"{ ""aaaa"": 1, ""bbbb"": ""qwerty"", ""ccc"": 21.22 }";
var jobject = Newtonsoft.Json.Linq.JObject.Parse(json);
var names = jobject.Root.Cast<JProperty>().Select(x => x.Name).ToArray();
That gives:
aaaa
bbbb
ccc
Deserialize the json to Dictionary using JsonConvert
Note: This will work if the key are always unique
var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
Console.WriteLine($"{string.Join(",", result.Keys)}");
just in one line
IEnumerable<string> names = JObject.Parse(json).Properties().Select(x => x.Name);
this will include the names of nested objects properties
IEnumerable names = JObject.Parse(json).Descendants().OfType<JProperty>()
.Select(x => x.Name);

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.net custom dictionary format

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.

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

Trying to convert JSON to [Key,Value] dictionary

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

Categories