using c# - I have a string of valid json, and am attempting to parse it into a Dictionary but am struggling with the syntax to do so.
Here's an example of the data I'd like to parse:
{
"data": {
"KeyOne": {
"val": "first!"
"fooBar": "invalid data not needed",
},
"anotherKey": {
"val": null
},
"TheThirdKey": {
"val": 999
"fooFooBarBar": "more unneeded data",
},
"KeyKeyKey": {
"val": "super neato something"
},
...
this needs to be moved into a Dictionary<string, object> with some fairly specific rules:
the ever changing element name is the key ('KeyOne', 'anotherKey'...) - this is unique within the dataset
for the dictionary value, I ONLY need the string or number or null that is the value of 'val' ('first', null, 999, ...)
so my final dictionary should be something like:
"KeyOne" : "first!"
"anotherKey" : null
"TheThirdKey": 999
"KeyKeyKey" : "super neato something"
I've tried to parse this using different variations of
JsonConvert.DeserializeObject<Dictionary<string, object>
I've also tried iterating over the jTokens as such:
JObject jObject = JObject.Parse(jsonString);
List<JToken> jTokens = jObject["data"].Children().ToList();
foreach (JToken jToken in jTokens) { ...
but after so many hours of trying, I am getting embarrassingly nowhere... Hopefully this is something that can be performed with Json.NET, but I have yet to figure it out.
Thoughts?
You could do it this way:
JObject jObject = JObject.Parse(jsonString);
var dataChildren = jObject["data"].Children().Cast<JProperty>();
Dictionary<string, object> result = dataChildren
.ToDictionary(x => x.Name, x => x.Value["val"].Value<JValue>().Value);
You will get a Dictionary<string,object> as a result
Related
Given the following JSON
{
"enabled": true,
"name": "Name",
"description": "Test",
"rules": [
{
"propA": "a",
"propB": "b"
}
]
}
Is it possible in C# to deserialize on selected properties based on an input list:
var propertiesToInclude = new List<string> { "description", "rules.PropA" };
The example json is a simplified example, the real one can contain hundred of properties. The use case is to only return the fields that matches the input list in a dynamic or anonymous object and discard the other properties.
using Newtonsoft.Json.Linq;
var propertiesToInclude = new List<string> { "description", "rules.PropA" };
var splitted = propertiesToInclude.SelectMany(x => x.Split('.'));
string text = File.ReadAllText("test.json");
var json = JToken.Parse(text);
Process(json);
Console.WriteLine(json);
void Process(JToken token)
{
if (token is JObject jObject)
{
jObject.Properties()
.Where(x => !splitted.Contains(x.Name, StringComparer.OrdinalIgnoreCase))
.ToList()
.ForEach(x => x.Remove());
foreach (var x in jObject)
Process(x.Value);
}
else if (token is JArray jArray)
{
foreach (var x in jArray)
Process(x);
}
}
This code on the data shown will give the desired result.
The output is a JToken object containing the desired properties.
However, I used a simple search for all occurrences of names in a splited array. This will give false positives if, for example, the root object contains the propA property or the object in the array contains the description property.
To avoid this, you need to compare the JToken.Path property with the propertiesToInclude elements, taking into account the depth.
I am trying the convert my json string into dictionary but could not successful.
{
"healths": [
{
"serviceName": "UserMgt",
"subService": [
{
"subServiceName": "Base",
"status": 10
},
{
"subServiceName": "Url",
"description": "Url is bad",
"status": 10
},
{
"subServiceName": "Configuration",
"status": 2
}
]
},
{
"serviceName": "ConfigurationMgt",
"subService": [
{
"subServiceName": "url",
"description": "urlis OK!",
"status": 2
},
{
"subServiceName": "Configuration Db",
"status": 2
}
]
}
}...and so son
So, as you see we have a service name, and based on that we have subserviceName then again service name and subservicename.Basiclly i want to convert this into dictionary as a key-value pair so that based on the key(service) we have values subservice(again a key value pair).
I tried many things but does not get a proper result.
like for example using newtonsoft nuget.
JObject jsonObj = JObject.Parse(formattedJson);
Dictionary<string, object> dictObj = jsonObj.ToObject<Dictionary<string, object>>();
foreach(var kv in dictObj)
{
Console.WriteLine(kv.Key + "::::" + kv.Value);
}
In this scenario I am getting output like key as a healths and every thing as a value.
Can anyone please help me regarding this.The Json and c# is new for me.
Thanks In Advance.
Assuming that you are guaranteed to have the described structure, you can deserialize to JObject and use LINQ's ToDictionary to process it:
var dict = JsonConvert.DeserializeObject<JObject>(json)["healths"]
.ToDictionary(
s => s["serviceName"].ToString(),
s => s["subService"]
.ToDictionary(ss => ss["subServiceName"].ToString(), ss => ss["status"].ToString()));
Where you can change ss => ss["status"].ToString() to select what is actually needed as subService value.
I am trying to parse Neo4jClient's query result of paths (of type string) using JsonConvert.
I was able to parse the query result for nodes using this method:
var _gClient = new GraphClient(new Uri("http://localhost:7474/db/data"));
_gClient.Connect();
var result = _gClient.Cypher
.Match("(n)")
.Return(n => n.As<string>())
.Results.ToList();
result.ForEach(n =>
{
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(n);
Console.WriteLine("Keys: " + String.Join(",", dict.Keys));
Console.WriteLine("Values: " + String.Join(",", dict.Values));
});
However, when I tried to do the same with the query result of paths, JsonConvert's DeserializeObject method can't do the same thing:
var _gClient = new GraphClient(new Uri("http://localhost:7474/db/data"));
_gClient.Connect();
var result = _gClient.Cypher
.Match("p=(a)-[:ACTED_IN]->(m:Movie {title:'The Matrix'})")
.Return(p => new
{
Nodes = Return.As<IEnumerable<string>>("EXTRACT(p in nodes(p) | p)"),
Relationships = Return.As<IEnumerable<string>>("EXTRACT(p in relationships(p) | p)")
})
.Results.ToList();
foreach (var n in result)
{
foreach (var s in n.Nodes)
{
JsonConvert.DeserializeObject<Dictionary<string, string>>(s);
}
}
The error was Unexpected character encountered while parsing value: {. Path 'extensions', line 2, position 17.
This is part of the string to be parsed:
{
"extensions": {},
"metadata": {
"id": 8,
"labels": [
"Person"
]
},
Does that mean Json can't deserialize empty braces? If so is there any other way I can parse this huge structure out?
The problem is that you're trying to deserialize into a Dictionary<string,string> but your JSON isn't a Dictionary<string,string> the error about the unexpected { is because for it to be a Dictionary<string,string> the JSON would look like:
{
"Key1" : "Value1",
"Key2" : "Value2"
}
The { on both extensions and metadata imply that there is an object there, not just a string. To that end you can deserialize it using something like:
JsonConvert.DeserializeObject<Dictionary<string, object>>(s)
But if you want to access the properties, you may as well do:
JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(s)
I have json file like this:
{
"fields": {
"customfield_10008": {
"value": "c1"
},
"customfield_10009": {
"value": "c2"
}
...
}
}
and I would like to create dictionary in c# like:
key: value
"customfield_10008":"c1"
"customfield_10009":"c2"
How I can achive this? I load json in this way,
dynamic json = JsonConvert.DeserializeObject(File.ReadAllText("data.json");
and don't know how to create dict like above
A little bit linq tricks can help you
var dict = JObject.Parse(File.ReadAllText("data.json"))["fields"]
.Cast<JProperty>()
.ToDictionary(x => x.Name, x => (string)x.Value["value"]);
Come through the values and collect them:
var result = new Dictionary<string, string>();
foreach (var field in obj.fields)
{
result.Add(field.Name, Convert.ToString(field.Value.value));
}
If you have json which do not have type in compile time, you can use dynamic type at that time.
I would parse above json using dynamic type and generate dictionary with parsed value :
var dicValues = new Dictionary<string,string>(); // this dictionary contains key value pair result
dynamic res = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText("data.json");
dynamic availableFields = res["fields"];
if (availableFields != null)
{
foreach (var field in availableFields)
dicValues.Add(field.Name, field.Value["value"].Value);
}
I'm trying to retreive a json item from a json string,this is my json for example:
{
"users":{
"john":{
"password":"0506777031",
"level":1
},
"doe":{
"password":"john",
"level":1
},
"dasda":{
"password":"das",
"level":"1"
},
"zuri":{
"password":"zuri123",
"level":2
}
}
}
I use the json.net library,this is what i've tried so far:
JObject json = JObject.Parse(jsonstring); //this is thr string
JObject match = json["users"].Values<JObject>().Where(m => m["username"].Value<string>() == "itapi" && (m["password"].Value<string>() == "0506777031")).FirstOrDefault();
I'm getting an error on the second line.
This is the error:
Cannot cast Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JToken.
I'm not sure what i'm doing wrong,i will appreciate any help! thanks!
Assuming your question is "What am I doing wrong?", the answer would be
You are trying to typecast what is a JProperty into a JObject (JProperty has a property named Value you can access).
You are not traversing the JSON syntax tree properly.
There is no mention of the "username" within the JSON sample provided.
If the usernames in your example are the property keys (names) "john", "doe", "dasda" and "zuri"... The query you probably want is as follows:
var match = json["users"].Values<JProperty>().Where(m => m.Name == "doe" && m.Value["password"].ToString() == "john").FirstOrDefault();
EDIT: Alternatively, if the username is that key, you can use the direct lookup and assign to the variable match only if the password matches the one you are trying to compare. Also the following version will return the JObject and not the JProperty as it seems you originally wanted. This should also be more efficient.
JObject match;
var temp = json["users"]["doe"];
if(temp["password"].ToString() == "john")
{
match = temp.ToObject<JObject>();
}
Shouldn't it be using square brackets for "users"?
{
"users":[
"john":{
"password":"0506777031",
"level":1
},
"doe":{
"password":"john",
"level":1
},
"dasda":{
"password":"das",
"level":"1"
},
"zuri":{
"password":"zuri123",
"level":2
}
]
}