Correctly iterating through json array - c#

I am trying to parse through an json array and get the values from it but facing some issues.
I have my json that I get as:
[{
"ID1":"1",
"ID2":"2",
"ID3":"3",
"ID4":"4"
},
{
"ID1":"5",
"ID2":"6",
"ID3":"7",
"ID4":"8"
}]
The key ID1, ID2 etc are not fixed. For ex I can also have my json as:
[{
"ID1":"1",
"ID2":"2"
},
{
"ID1":"5",
"ID2":"6"
}]
Or there can be more keys also, ie its dynamic so I cant create a model and map my json to it.
I was trying to deserialize that and get the data by using the following code.:
public IActionResult GetData(string data)
{
//here data is my json
List<string> myList = JsonConvert.DeserializeObject<List<string>>(data);
foreach (string s in myList)
{
//get values here
}
return Json("");
}
But above gives me error when deserializing as:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while >parsing value: {. Path '', line 1, position 2.'
So I wanted to know how what is the correct method to loop through this json and get key values from it.

Your JSON is a list of object, your issue is that you are trying to deserialize into a list of string. This will not work for obvious reasons.
Instead you want to deserialize into a list of objects, and since your objects keys change the best thing you can use is a Dictionary<string, string>:
var myList = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(data);
Keep in mind that the JSON you posted is a Dictionary<string, string> but as soon as you get integers or bools in that JSON you should change to Dictionary<string, object>
Fiddle here

Related

Cannot deserialize Json file to a list of KeyValuePair with string "key"

I have hard time deserializing the json response from Solr search engine.
I use Newtonsoft Json.NET.
Simplified response from Solr:
{
"suggestions": [
{
"someword": {
"numFound": 1
}
}
]
}
I deserialize this to a list of KeyValuePair<string, customobject>.
customobject test = Newtonsoft.Json.JsonConvert.DeserializeObject<customobject>(jsonText);
It worked, until a user typed the word "key", so Solr returned that JSON:
{
"suggestions": [
{
"key": {
"numFound": 1
}
}
]
}
The deserialization of this JSON raise this error :
Unexpected character encountered while parsing value
...
Ok. I just realized that even if it doesn't raise an exception with words other than "key", it doesn't work because the KeyValuePair in the output object are always empty.
I had never realized this problem before because this part of the Json (Spellcheck Suggestions) is never used.
So easy fix: we do not serialize suggestions anymore.
But, if anyone still want to answer the question, in what kind of object will you deserialize this Json (from Solr)?
{
"suggestions":
[
{"brack":{
"numFound":10,
"startOffset":0,
"endOffset":5,
"origFreq":0,
"suggestion":[{
"word":"back",
"freq":78},
{
"word":"black",
"freq":1}
]}},
{"key":{
"numFound":1,
"startOffset":6,
"endOffset":9,
"origFreq":12,
"suggestion":[{
"word":"key",
"freq":15}]}}]
}
I don't think a dictionary can do the job :
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,Test.SpellCheckSuggestion]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
As mentioned in a comment above, the solution is to use a list of dictionary. (not just a dictionary and not a list of KeyValuePair)
List<Dictionary<string, SpellCheckSuggestion>>

C# JSON; Deserialize array that sometimes has an empty value (not null)

I'm trying to deserialize a JSON response and I want a function that detects if the array is empty and if it is not empty I want it to return the values.
The JSON array looks like this when empty:
{"metrics":[]}
And when it is not empty it can look like any of the below:
{"metrics":["flow"]}
{"metrics":["energy"]}
{"metrics":["flow","energy"]}
How can I detect this?
It does not work with NullValueHandling since if the array is empty it is not null, it doesn't have any values at all.
I jus get an error about index is not found.
I am returning the array as a List in my classes.
Assuming you're using Newtonsoft.Json for deserializing the json:
class Data
{
public List<string> Metrics { get; set; }
}
var json = "{\"metrics\":[]}";
var obj = JsonConvert.DeserializeObject<Data>(json);
obj.Metrics will be an empty collection, not null.
Plus, even if it was, you could access it like
var metrics = obj.Metrics ?? new List<string>();

Dynamically serialise JSON with the ability to omit entries

I am using an API that frustratingly requires you to omit optional parameters rather than pass them as null.
Also, data is slightly nested in the format:
{ data: { prop1: 5, prop2: 6, prop3: 7 } }
Previously I was converting it using a replace:
"{ data: { prop1: {prop1}, prop2: {prop2}, prop3: {prop3} } }"
.Replace("{prop1}", prop1)....
But it turns out that if a value is not provided the API I am sending this to will only accept it if it's not included in the JSON.
Rather than mess around with complex string concatenation (as I am not using model binding), I thought about simply creating a dictionary and serialising it to JSON.
If I do this:
Dictionary<string, int> props = new Dictionary<string, int>
{
{ "prop1", 6 },
{ "prop3", 7 },
};
string json = JsonConvert.SerializeObject(props, Formatting.Indented);
I can serialise whichever props I need nicely. Unfortunately you can see the way I need to send the data is contained within the data property of the json. I would need to put a dictionary inside my dictionary, but the dictionary is defined as string, int so that isn't possible. If I changed the type, then I'd not be able to put my props in.
To solve this I can see 2 possible clean ways:
Dynamically compose a JSON object somehow sorta like XML
eg. new JsonObject().AddNode("data").AddProperty("Prop1", 3).AddProperty("Prop3", 5).... etc.
Serialise from a dictionary object in a way that will let me include the nested property. Or, find a way to assign the json from a non-nested dictionary into the data property of a new json object.
I've not found a way to do this cleanly yet - alternatively another suggestion on solving this issue would be appreciated.
Not sure what your problem is with the dictionary approach. This works fine:
var props = new Dictionary<string, Dictionary<string, int>>
{
{ "data", new Dictionary<string, int>
{
{"prop1", 6},
{"prop3", 7}
}
}
};
var json = JsonConvert.SerializeObject(props, Formatting.Indented);

Convert Dictionary to JSON in C#

first time asking questions here.
I currently have a Dictionary in C# that I want to serialize into JSON using:
Dictionary<string, List<string> myDict = new Dictionary<string, List<string>();
string json = JsonConvert.SerializeObject(myDict);
Works A1, getting results
{"Key1":["Item1","Item2","Item3"],"Key2":["Item1","Item2","Item3"]}
However, I would like to get my JSON response in this format to be usable with Jquery addons:
{"ID":"Key1", "Value": ["Val":"Item1","Val:":"Item2","Val":"Item3"]
}, { "ID":"Key2",
"Value":["Val":"Item1","Val:":"Item2","Val":"Item3"] }
Without having to loop through the dictionary and rebuild it manually. Is there any decent ways to do it?
Thank you

Easily working on a json object

I'm deserializing (or parsing) a json string to a c# object (using Json.NET) and getting a JObject. I want to iterate all the properties with the key "bla", in the same way iterating all xml elements that named "bla" with XElement.Elements("bla").
If it's not possible, I would like to deserialize my json string into a c# object, and work dynamically and recursively on my deserialized json object (my json string can have lists / arrays that can have objects of 2 types.
In the end after editing my object (changing values and removing or adding properties) I need to serialize my object back to a json string.
Which is the best and easiest way to use json serializing and deserializing?
my Json looks like this:
{"Families":{"Family":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}, {"propA":"dhsj", "propB":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}, {"propA":"dhsj", "propB":"fghfgh"}]}]}
in conclusion, the json value is a json object that it's value is a list/array, the list/array can contain 2 "types" of objects, and one of these types also has a property which it's value is a json object that it's value is a list/array, and it goes like this recursively. sometimes the value of one of the props of the type that doesn't have a property which it's value is a json object that it's value is a list/array, can be a list/array itself, that can contain only 1 type of the two mentioned.
If you don't need a strongly-typed object, you can deserialize to a dictionary:
Dictionary<string, object> myObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
And then just use it as a dictionary:
myObject["Property"] = value;
Or
foreach(var propertyKey in myObject.Keys)
{
// do something with each property
Console.WriteLine($"{propertyKey} = {myObject[propertyKey]}");
}
Here's a fiddle
You can serialize it back after you are done
My json looks more like this:
{"Familys":{"Family":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}]}
For JSON like this:
var json = #"{
""Families"":{
""Family"":[
{
""propA"":""Top""
},
{
""propA"":""Top.Lower"",
""Families"":{
""Family"":[
{
""propB"":""propB value""
},
{
""propA"":""Top.Lower.EvenLower"",
""Families"":{
""Family"":[
{
""propA"":""Top.Lower.EvenLower.EvenLower""
}
]
}
}
]
}
}
]
}
}";
Do something like this:
//calling code makes use of "dynamic" to make things clean and readable.
dynamic parsedJson = JsonConvert.DeserializeObject(json);
var allPropAValues = GetPropAValues(parsedJson);
//**** NOTE: this has our extra property ****
var jsonWithExtraStuffProperty = JsonConvert.SerializeObject(parsedJson);
//recursive function that reads AND writes properties
public static List<string> GetPropAValues(dynamic obj)
{
var propAValues = new List<string>();
//**** NOTE: the use of an added property ****
obj.ExtraStuff = new Random().Next();
//if we have a propA value, get it.
if (obj.propA != null)
propAValues.Add(obj.propA.Value);
//iterate through families if there are any. your JSON had Families.Family.
if (obj.Families != null)
foreach (dynamic family in obj.Families.Family)
propAValues.AddRange(GetPropAValues(family));
return propAValues;
}

Categories