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
}
]
}
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 have the following json
{
"audit_date": "2020-05-13T11:27:10.3187798Z",
"client_uuid": "2fd77dd8-ed76-4bba-b0e1-5cda454c8d6e",
"audit_entry": {
"where_uri": "test.com/dataservice/apps/171f0841-825b-4964-8f8c-0869650f14a6",
"why_uri": "test.com/dataservice/reference/reasons_for_change/61acc173-7168-4ae5-9f04- afa228941f8b",
"who_uri": "test.com/securityservice/users/4977dae1-a307-425f-980c-53413fef1b0f",
"when_audited": "2018-11-13T20:20:39+00:00",
"what_uri": "test.com/dataservice/study_subjects/1bc67a71-8549-4ab8-9dd9-e44238198860",
"what_changed": [
{
"attribute_name": "birth_year",
"attribute_value": "1969",
"attribute_change": "1970"
},
{
"attribute_name": "subject_reference",
"attribute_value": "TEST-WOO3444",
"attribute_change": null
}
]
}
}
And I want to remove the second attribute_change key value pair to be as follows
{
"audit_date": "2020-05-13T11:27:10.3187798Z",
"client_uuid": "2fd77dd8-ed76-4bba-b0e1-5cda454c8d6e",
"audit_entry": {
"where_uri": "test.com/dataservice/apps/171f0841-825b-4964-8f8c-0869650f14a6",
"why_uri": "test.com/dataservice/reference/reasons_for_change/61acc173-7168-4ae5-9f04- afa228941f8b",
"who_uri": "test.com/securityservice/users/4977dae1-a307-425f-980c-53413fef1b0f",
"when_audited": "2018-11-13T20:20:39+00:00",
"what_uri": "test.com/dataservice/study_subjects/1bc67a71-8549-4ab8-9dd9-e44238198860",
"what_changed": [
{
"attribute_name": "birth_year",
"attribute_value": "1969",
"attribute_change": "1970"
},
{
"attribute_name": "subject_reference",
"attribute_value": "TEST-WOO3444",
}
]
}
}
I have tried the following code
JObject jObject = JObject.Parse(jsonText);
JObject jObj = (JObject)jObject.SelectToken("audit_entry");
//remove second attribute changed token
jObj.Property("what_changed")("attribute_change")[1].Remove();
string json = jObj.ToString(Formatting.None);
I know the syntax is wrong for jObj.Property but after a few hours of googling I cannot find the answer.
Any help much appreciated.
You can remove a property from JObject by calling Remove method with corresponding property name. For example:
JObject jObject = JObject.Parse(jsonText);
// find required object, there are other options
// for example (JObject)jObject["audit_entry"]["what_changed"][1]
var nested = (JObject)jObject.SelectToken("$.audit_entry.what_changed[1]");
//remove attribute changed token
nested.Remove("attribute_change");
string json = jObject.ToString(Formatting.None); // attribute_change is removed from jObject
If you want to remove all properties with such name and null for value you can do next:
var toRemove = jObject.Descendants()
.OfType<JProperty>()
.Where(prop => prop.Name == "attribute_change" && prop.Value.Type == JTokenType.Null)
.ToList();
foreach (var prop in toRemove)
{
prop.Remove();
}
Since what_changed is an array, you should cast to JArray to be able to access its elements and remove attribute_change token
var jObject = JObject.Parse(jsonText);
if (jObject["audit_entry"]?["what_changed"] is JArray array)
if (array[1] is JObject attribute)
attribute.Remove("attribute_change");
Console.WriteLine(jObject);
Search for the beginning attribute name and its end. Then concatenate the json string before/after into a new string. Perhaps a hack, but it will keep you coding until you find a more elegant solution.
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
How to fetch "full_name_ac" in the following JSON :-
{
"rows": 10,
"os": "0",
"page": "1",
"total": "1",
"peoples": {
**"123":** {
"url": "http://google.com",
**"id": "123",**
"fname": "Rob",
"lname": "Tom",
"full_name_ac": "Rob Tom"
}
}
}
I can not create model because model is always going to be changed according to "id".
I am trying something like that but not sure how to get the value of full_name_ac
JObject obj = JObject.Parse(data);
I'd recommend you take a look at using JSONPath(s) and use SelectTokens:
JObject obj = JObject.Parse(data);
var names = obj.SelectTokens("$.peoples.*.full_name_ac");
var allNamesAsCsv = String.Join(",", names.Values<string>());
Of course, if you always know that there will always be just one, you can use SelectToken:
var onlyMatchObject = obj.SelectToken("$.peoples.*.full_name_ac");
var onlyMatch = first.Value<string>();
Use Json.Net. try to use dyanamic
dynamic stuff = JsonConvert.DeserializeObject(YOUR-JSON_STRING);
string name = stuff.peoples.123.full_name_ac;
See this link for more info:Deserialize JSON into C# dynamic object?
model is always going to be changed according to "id".
If your model is always changes then you have create one model which contains id and string. String object is a json string of fields. So that you can check Id and it's model fields. so you can compare that fields with json.
"field" :
{
"id" : 123
"fields" :
{
"fname":"string",
"full_name_ac":"string"
}
}
Create json something like above and include this json in your json. When you deserialize your main json you can compare fields. I thing from above you will get some basic idea.
If your model is dynamic then there is only one option i.e. you have
to create a json something like above which contains fields. So that you can
compare that fields with your actual json value.
Maybe you can use a Regex and some basic text parsing, to identify the "full_name_ac" property, and subtract the value, something like:
// just an example, untested
string jsonText = "{...}";
int startIndex = jsonText.indexOf(#"""full_name_ac"":");
int stopIndex = jsonText.indexOf(startIndex, "}");
string value = jsonText.substring(startIndex, stopIndex);
Fetch the value of required token of the deserialized object (in your case obj.peoples has first token as "123" and first token of "123" is the object which has the required properties) and get the required property i.e. full_name_ac from it.
dynamic obj = JObject.Parse(jsonText);
var value = obj.peoples;
var tokenPeople = ((Newtonsoft.Json.Linq.JContainer)obj.peoples).First.First;
string peopleJson =tokenPeople.ToString();
dynamic people = JObject.Parse(peopleJson);
string full_name_ac = people.full_name_ac;
Following line will help you to get the value of full_name_ac
var full_name_ac = obj.SelectToken("peoples.123.full_name_ac").ToString();
using JObject.Parse(jsonString) AND get First element
// Id is dynamic , so parse and get first element
string dynamicName = (string)JObject.Parse(data)["peoples"].Children().First().Children().First()["full_name_ac"];
I would like to make a Linq query in a json string.
little info about what i'm trying to do. At work we have a web based schedule system which don't have a support for windows 8 and windows phone 8 app. That is why I decided to make one. Using HttpClient I get an http string which I then convert to xml then Json. As you can see from the (Link below, the 'TheWholeJsonString.json' file) the property name and JSON object name is not informative and the JSON file is complicated. That is why I decided to extract some of the values from the JSON string and write a totally new JSON file that include the extracted JSON values in a more informative way.
The [tr] array in the original JSON file have several JSON Objects. Inside the 'VeryShorten.json' file in the linked folder you can see the structure of one of those objects (OBS! there is objcet with different structure). The only thing I hide is the Name and E-Mail address of RL ppl.
I also attached 'ShortenVersion.json' which is only a shorten version of the whole json string, just to make it easy to handle.
Json data sample
{
"#class": "odd",
"td": [
{
"#class": "user",
"#onmouseover": "userInfo('149');",
"#onmouseout": "userInfo(0);",
"#onmousemove": "moveSlotInfo();",
"#text": " ",
"a": {
"#href": "Name3#dreamnet.com",
"#text": "Name3"
}
},
.
.
.
In C# if i try the following code (which is not Linq)
var jObject = JObject.Parse(jString); //jString is 'TheWholeJsonString.json' file in the attached link
var jObj = jObject["tbody"]["tr"][8];
var gh = jObj.Value<JToken>("td").Children().First().Value<JToken>("a").Value<string>("#text");
i can get the value of '#text' which is *'Name3'.
However if i try the following code (Linq version):-
var jObject = JObject.Parse(jString);
var jCollection = jObject["tbody"]["tr"].Children();
var test = from userToken in jCollection
where
userToken.Value<JToken>("td")
.Children()
.First()
.Value<JToken>("a")
.Value<string>("#text")
.Contains("Name3")
select (string)userToken["#text"];
foreach (var item in test)
{
var fgh = item.Type;
}
It will break on the first iteration of foreach loop with the following error msg "Cannot access child value on Newtonsoft.Json.Linq.JValue". I really now what is causing the problem, but i don't know how to solve it. The problem is that not every token inside jCollection have a 'td' object and even if the token have 'td' object it is not Always it have token 'a'. You can see this either in the 'TheWholeJsonString.json' or 'ShortVersion.json' files which i attached in the link.
Hope this will explain more info.
So the question is:- Anyone can help to solve this problem?
You can use SelectTokens method. Notice false as second parameter - don't generate error if element is not found.
var jObject = JObject.Parse(jString);
var trList = jObject["tbody"]["tr"];
string[] names = trList.SelectMany(tr => tr.SelectTokens("td[0].a.#text", false))
.Select(t => t.Value<string>())
.ToArray();
You can easily query with LINQ like this
considering this JSON
{
"items": [
{
"id": "10",
"name": "one"
},
{
"id": "12",
"name": "two"
}
]
}
putting it in a variable called json like this,
JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");
you can select all ids from the items where name is "one" using the following LINQ query
var Ids =
from item in json["items"]
where (string)item["name"] == "one"
select item["id"];