I'm trying to debug my JProperty object but somehow I can not get all the data out of this object. When I debug te JProperty it says it has the data im trying to recieve but I'm only able to obtain a part of it, explanation:
So my response JSON looks like this:
{"url":"www.microsoft0nline.nl\/test.php","time":"2019-06-19 09:50:49","stringvalue":"otherValue1","intvalue":433,"array":["35","37","43"],"otherObject1":{"name":"object1","description":"A object type","size":120}}
I'm iterating through this with the following code:
foreach (JProperty property in jsonResponse.Properties())
{
}
So when I run my code in debug mode and i debug these properties I'm getting the following:
As you all can see the parent of property has the object "otherObject1" within.
Now I iterate through this property with the following code:
foreach (var itemsOfResponse in property)
{
var dataJson = itemsOfResponse;
System.Diagnostics.Debug.WriteLine(dataJson);
}
And the response in my debugger looks like this:
www.microsoft0nline.nl/test.php
2019-06-19 10:01:49
otherValue1
433
[
"35",
"37",
"43"
]
The response contains all the values of my json response exept the one of "otherObject1", how is this possible? And is there a way to obtain the key values(url, stringvalue, intvalue, etc) of these properties to?
Hope someone can help me out here!
JProperty is only a single name value token pair.
JObject will contain many JToken objects (including JProperty and JObject instances).
For what you are trying to do, you should probably use JToken as both JProperty and JObject are JToken derived classes.
Related
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": null
},
{
"attribute_name": "subject_reference",
"attribute_value": "TEST-WOO3444",
"attribute_change": null
}
]
}
}
But I want to empty the nest array "what_changed"
So I need the output to be
{
"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": []
}
}
I have written the following code
JObject jObj = JObject.Parse(jsonText);
jObj["audit_entry"]["what_changed"] = null;
string json = jObj.ToString(Formatting.None);
but this makes the field null rather than empty array.
I have also tried
JObject jObj = JObject.Parse(jsonText);
jObj["audit_entry"]["what_changed"] = "";
string json = jObj.ToString(Formatting.None);
but that still doesn't give an empty array.
I also tried using the Array.Clear() method, but this is a JObject array rather than a normal array.
Arrays are represented by the JArray type, not JObject. Cast the value of "what_changed" to the proper type and use the methods you need. Eg:
JObject jObj = JObject.Parse(jsonText);
JArray changed=(JArray)(jObj["audit_entry"]["what_changed"]);
changed.Clear();
Working with JSON elements is rather unusual though. It's typically a lot easier to deserialize JSON strings into strongly typed objects, modify them as needed and then serialize them back to a string.
Generating the necessary DTOs can be done easily in Visual Studio by selecting Paste Special > Paste JSON as Classes from the Edit menu
I can see several possibilities...
1.- instead of clearing the array, create a new one, an empty one. This does not solve the problem but it is a work around.
2.- using newtonsoft (a nuget package that you can download), you may be able to find different utilities there.
2.1.- Instead of parsing with JObject, parse with JArray, and then use Clear:
https://www.newtonsoft.com/json/help/html/ParseJsonArray.htm
https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JArray_Clear.htm.
2.2.- use Remove, for this you need the property name, so you need to iterate within the array (a foreach), getting the name of the property, and delete one by one.
https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JObject_Remove.htm
You need to cast it to a JArray first, then you can use its Clear() method;
((JArray)(jObj["audit_entry"]["what_changed"])).Clear();
Alternatively, you could simply create a new JArray in place of the old one.
jObj["audit_entry"]["what_changed"] = new JArray();
Try this :
JObject jObj = JObject.Parse(jsonText);
JToken jToken = jObj["audit_entry"]["what_changed"];
jToken.Replace(JToken.Parse("[]"));
string json = jObj.ToString(Formatting.None);
I have the following json parsed into a JObject:
JObject json = JObject.Parse(#"{
""event"": {
""name"": ""daniel""
},
""markets"": [
{}
]
}");
With that JObject I'm trying to retrieve the empty JObject that's in the markets JArray.
I'm currently trying json.SelectToken("$.event.markets[0]") but that's not working, it returns null rather than the empty JObject that I expect.
Is there a way to get that empty JObject by using the SelectToken || SelectTokens method? I'd prefer to stay away from using linq, but if I must I must.
This should be json.SelectToken("$.markets[0]") instead of json.SelectToken("$.event.markets[0]") as markets is not contained within the event object.
I have a JObject equal to:
"Info":
{
"View":"A",
"Product":"B",
"Offer":"Offer1",
"Demo":"body {background-color:red;} #box {border:dotted 50px red;}",
"Log":false
}
How can I return the name of the object, "Info"?
I am currently using the Path property like so:
jObject.Name = jObject.Path.Substring(jObject.Path.jObject('.') + 1);
Is there a better way to do this?
In JSON, objects themselves do not have names. An object is just a container for a collection of name-value pairs, beginning and ending with curly braces. So what you have above is a fragment of a larger body of JSON. There must be an outer object to contain it. That outer object has a property with a name of Info, and the value of that property is the object you are referring to.
{
"Info":
{
"View":"A",
"Product":"B",
"Offer":"Offer1",
"Demo":"body {background-color:red;} #box {border:dotted 50px red;}",
"Log":false
}
}
In Json.Net, a JObject models a JSON object, and a JProperty models a name-value pair contained within a JObject. Each JObject has a collection of JProperties which are its children, while each JProperty has a Name and a single child, its Value.
So, assuming you have a reference to the innermost JObject (containing the View, Product and Offer properties), you can get the name of its containing JProperty like this:
JProperty parentProp = (JProperty)jObject.Parent;
string name = parentProp.Name; // "Info"
So I'm trying to control deserialization by reading a json object as a JObject, deleting some fields, and then deserializing it again to my target object using Json.Net. The problem is, any time I try to delete a field, I get the error:
An unhandled exception of type 'Newtonsoft.Json.JsonException'
occurred in Newtonsoft.Json.dll
Additional information: Cannot add or remove items from
Newtonsoft.Json.Linq.JProperty.
Here's my (simplified, but still causing the error) code:
JToken token = (JToken)JsonConvert.DeserializeObject(File.ReadAllText(fileName));
foreach (JToken inner in token["docs"])
{
if (inner["_id"] != null)
inner["_id"].Remove();
MyObject read = new MyObject();
JsonConvert.PopulateObject(inner.ToString(), read);
Values.Add((MyObject)JsonConvert.DeserializeObject(inner.ToString(), typeof(MyObject)));
}
The json is a very large file where the docs array contains many elements as follows (again simplified for clarity):
{
"docs": [
{
"Time": "None",
"Level": 1,
"_id": "10208"
},
{
"Time": "None",
"Level": 1,
"_id": "10209"
}
]
}
Alternatively if there's a better way to deserialize JSON to a specific type, but still ignoring additional fields, that would be a fine alternative.
Assuming Values is a List<MyObject> and your MyObject class looks like this:
class MyObject
{
public string Time { get; set; }
public int Level { get; set; }
}
you can replace all that code with the following to get the result you want:
string json = File.ReadAllText(fileName);
Values = JToken.Parse(json)["docs"].ToObject<List<MyObject>>();
This works because Json.Net will ignore missing properties by default. Since the MyObject class does not contain an _id property to deserialize into, you don't need to jump through hoops trying to remove it from the JSON.
Explanation of why Remove() didn't work
JToken.Remove() removes a JToken from its parent. It is legal to remove a JProperty from its parent JObject, or to remove a child JToken from a JArray. However, you cannot remove the value from a JProperty. A JProperty must always have exactly one value.
When you ask for token["_id"] you get back the value of the JProperty called _id, not the JProperty itself. Therefore you will get an error if you try to call Remove() on that value. To make it work the way you are doing, you'd need to use Parent like this:
if (inner["_id"] != null)
inner["_id"].Parent.Remove();
This says "Find the property whose name is _id and give me the value. If it exists, get that value's parent (the property), and remove it from its parent (the containing JObject)."
A more straightforward way to do it is to use the Property() method to access the property directly. However, this method is only available on JObject, not JToken, so you would either need to change the declaration of inner to a JObject or cast it:
foreach (JObject inner in token["docs"].Children<JObject>())
{
JProperty idProp = inner.Property("_id");
if (idProp != null)
idProp.Remove();
...
}
Lastly, as mentioned in the comments, if you're using C# 6 or later you can shorten the code a bit using the null-conditional operator:
inner.Property("_id")?.Remove();
Based on brillian answer from Brian, you can do simply this in your case:
var inner_id = inner["_id"] as JProperty;
if (inner_id != null)
inner_id.Remove();
I'm receiving a JSON string in a MVC4/.NET4 WebApi controller action. The action's parameter is dynamic because I don't know anything on the receiving end about the JSON object I'm receiving.
public dynamic Post(dynamic myobject)
The JSON is automatically parsed and the resulting dynamic object is a Newtonsoft.Json.Linq.JContainer. I can, as expected, evaluate properties at runtime, so if the JSON contained something like myobject.myproperty then I can now take the dynamic object received and call myobject.myproperty within the C# code. So far so good.
Now I want to iterate over all properties that were supplied as part of the JSON, including nested properties. However, if I do myobject.GetType().GetProperties() it only returns properties of Newtonsoft.Json.Linq.JContainer instead of the properties I'm looking for (that were part of the JSON).
Any idea how to do this?
I think this can be a starting point
dynamic dynObj = JsonConvert.DeserializeObject("{a:1,b:2}");
//JContainer is the base class
var jObj = (JObject)dynObj;
foreach (JToken token in jObj.Children())
{
if (token is JProperty)
{
var prop = token as JProperty;
Console.WriteLine("{0}={1}", prop.Name, prop.Value);
}
}
EDIT
this also may help you
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jObj.ToString());