asp.net - How to get / deserialize object of JsonPatchDocument? - c#

I could serialize the JsonPatchDocument model by using JsonConvert.SerializeObject(), but the type of result is string, how can I convert it to normal array type? Or how to get JsonPatchDocument object straight to array?
var pathSerialized = JsonConvert.SerializeObject(patch);
Console.WriteLine(pathSerialized);
// Result as string:
// "[{"value":"2018-08-30","path":"/openTo","op":"replace"},{"value":"2018-04-01","path":"/openFrom","op":"replace"}]"

You don't have to serialize the JsonPatchDocument object at all. You can access its properties directly through the object. For example filtering for the path property:
var elementsWithPath = patch.Operations.Where(o => o.path.Equals("some path"));

I think you might be looking to do something with JTokens from the Newtonsoft.Json.Linq namespace. You can turn the pathserialized string into a JToken with var jToken = JToken.Parse(pathSerializer), then explore the underlying objects and properties by enumerating them with var childTokens = jToken.Children().
One of those child tokens is going to be a JObject, which is a Json representation of an object. You can access properties of a JObject with jObject["propertyName"].

Related

JContainer, JObject, JToken and Linq confusion

I am having trouble understanding when to use JContainer, JObject, and JToken. I understand from the "standards" that JObject is composed of JProperties and that JToken is the base abstract class for all of the JToken types, but I don't understand JContainer.
I am using C# and I just bought LinqPad Pro 5.
I have a JSON data source in a file, so I'm deserializing that file's contents successfully using this statement:
string json;
using (StreamReader reader = new StreamReader(#"myjsonfile.json"))
{
json = reader.ReadToEnd();
}
At that point, I take the JSON string object and deserialize it to a JObject (and this might be my mistake--perhaps I need to make jsonWork a JToken or JContainer?):
JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);
In my JSON data (the string represented by JSON), I have three objects--the top-level object look similar to this:
{
"Object1" : { ... },
"Object2" : { ... },
"Object3" : { ... }
}
Each object is composed of all sorts of tokens (arrays, strings, other objects, etc.), so it is dynamic JSON. (I used ellipses as placeholders rather than muddying up this question wit lots of JSON data.)
I want to process "Object1", "Object2", and "Object3" separately using LINQ, however. So, ideally, I would like something like this:
// these lines DO NOT work
var jsonObject1 = jsonWork.Children()["Object1"]
var jsonObject2 = jsonWork.Children()["Object2"]
var jsonObject3 = jsonWork.Children()["Object3"]
But the above lines fail.
I used var above because I have no idea what object type I should be using: JContainer, JObject, or JToken! Just so you know what I want to do, once the above jsonObject# variables are properly assigned, I would like to use LINQ to query the JSON they contain. Here is a very simple example:
var query = from p in jsonObject1
where p.Name == "Name1"
select p
Of course, my LINQ ultimately will filter for JSON arrays, objects, strings, etc., in the jsonObject variable. I think once I get going, I can use LinqPad to help me filter the JSON using LINQ.
I discovered that if I use:
// this line WORKS
var jsonObject1 = ((JObject)jsonWork).["Object1"];
Then I get an JObject type in jsonObject1. Is this the correct approach?
It is unclear to me when/why one would use JContainer when it seems that JToken and JObject objects work with LINQ quite well. What is the purpose of JContainer?
You don't really need to worry about JContainer in most cases. It is there to help organize and structure LINQ-to-JSON into well-factored code.
The JToken hierarchy looks like this:
JToken - abstract base class
JContainer - abstract base class of JTokens that can contain other JTokens
JArray - represents a JSON array (contains an ordered list of JTokens)
JObject - represents a JSON object (contains a collection of JProperties)
JProperty - represents a JSON property (a name/JToken pair inside a JObject)
JValue - represents a primitive JSON value (string, number, boolean, null)
So you see, a JObject is a JContainer, which is a JToken.
Here's the basic rule of thumb:
If you know you have an object (denoted by curly braces { and } in JSON), use JObject
If you know you have an array or list (denoted by square brackets [ and ]), use JArray
If you know you have a primitive value, use JValue
If you don't know what kind of token you have, or want to be able to handle any of the above in a general way, use JToken. You can then check its Type property to determine what kind of token it is and cast it appropriately.
JContainer is a base class for JSON elements that have child items. JObject, JArray, JProperty and JConstructor all inherit from it.
For example, the following code:
(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")
Would throw an InvalidCastException, but if you cast it to a JContainer, it would be fine.
Regarding your original question, if you know you have a JSON object at the top level, you can just use:
var jsonWork = JObject.Parse(json);
var jsonObject1 = jsonWork["Object1"];
Most examples have simple json and I've googled "C# Newtonsoft parse JSON" more than once.
Here's a bit of a json file I was just asked to parse for a csv. The company name value is nested within many arrays / objects so it is semi-complicated in that regard.
{
"page": {
"page": 1,
"pageSize": 250
},
"dataRows": [
{
"columnValues": {
"companyName": [
{
"name": "My Awesome Company",
}
]
}
}
]
}
var jsonFilePath = #"C:\data.json";
var jsonStr = File.ReadAllText(jsonFilePath);
// JObject implementation for getting dataRows JArray - in this case I find it simpler and more readable to use a dynamic cast (below)
//JObject jsonObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
//var dataRows = (JArray)jsonObj["dataRows"];
var dataRows = ((dynamic)JsonConvert.DeserializeObject(jsonStr)).dataRows;
var csvLines = new List<string>();
for (var i = 0; i < dataRows.Count; i++)
{
var name = dataRows[i]["columnValues"]["companyName"][0]["name"].ToString();
// dynamic casting implemntation to get name - in this case, using JObject indexing (above) seems easier
//var name2 = ((dynamic)((dynamic)((dynamic)dataRows[i]).columnValues).companyName[0]).name.ToString();
csvLines.Add(name);
}
File.WriteAllLines($#"C:\data_{DateTime.Now.Ticks}.csv", csvLines);

JSON.net unserialize list of different objects

How can i unserialize a list of different objects uwing JSON.net?
string myJson = "[{action: 'a1', target: 4},{action: 'a2', targets: [1,2,3], {action:'a3', text:'targets altered'}}]";
This example presents a list of 3 different objects.
If I unserialize as a basic Object, I cannot access any members (as the base Object class doesn't have them).
I've looked over http://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm but I don't understand if it can help me.
with that method you posted, your json should contain extra info to indicate what type it is,which means you need to modify how the source of json to serialize,and make sure the you use the same class,namespace as the source serialized.
Or,use Object or dynamic as type of target, and to convert it in later use may be easier.
Use the dynamic type.
You can access elements as if they were properties. If a property doesn't exist, the dynamic type will return null instead of throwing an exception
dynamic actions = JsonConvert.DeserializeObject(myJson);
foreach (var action in actions)
{
var name = action.action.ToString();
var target = action.target.ToString();
var text = action.text.ToString();
if (target == null)
{
dynamic targets = action.targets;
}
}

How to parse a list of Integers from a JSON object

I'm using "Newtonsoft.Json.Linq.JObject" in my application.
I have a method that receives a JObject in the format:
{
"PersonnelIds": "[31,32,33,34]"
}
And I want to parse the content of PersonnelIds to a List of Integers.
What is the best way of doing that?
I can see that the values of the PersonnelIds is written as string "[31,32,33,34]" so to parse it with this syntax you can use the following code
JObject jObject = JObject.Parse(myjson);
JToken jToken = jObject.GetValue("PersonnelIds");
var array = JArray.Parse(jToken.Value<string>()).Select(x => (int)x).ToArray();
if your value is not string so your JSON is like {"PersonnelIds": [31,32,33,34]
} then you can parse it using the following code
JObject jObject = JObject.Parse(myjson);
JToken jToken = jObject.GetValue("PersonnelIds");
int[] array = jToken.Values<int>().ToArray();
Create a class to deserialize your json:
To create classes, you can copy the json in clipboard and use the
Edit / Paste special / Paste JSON as class
in visual studio (I use vs2013).
Then deserialize your string.
See my solution on this post

Turn a JSON string into a dynamic object

I'm trying to create a dynamic object from a JSON string in C#. But i can't get it done.
Normally i would get a JSON string through a web service call but in this case I simply created a simple class which I turn into a JSON string. Then I try to turn it back into a dynamic object with the exact same structure as if it was an instance of the Entity class. But that's where I'm having trouble.
This is the class that i turn into a JSON string:
public class Entity
{
public String Name = "Wut";
public String[] Scores = {"aaa", "bbb", "ccc"};
}
Then in somewhere in my code i do this:
var ent = new Entity();
// The Serialize returns this:
// "{\"Name\":\"Wut\",\"Scores\":[\"aaa\",\"bbb\",\"ccc\"]}"
var json = new JavaScriptSerializer().Serialize(ent);
dynamic dynamicObject1 = new JavaScriptSerializer().DeserializeObject(json);
dynamic dynamicObject2 = Json.Decode(json);
When I debug this code then i see that the first dynamicObject1 returns a Dictionary. Not really what I'm after.
The second dynamicObject2 looks more like the Entity object. It has a property called Name with a value. It also has a dynamic array called Scores, but for some reason that list turns out to be empty...
Screenshot of empty Scores property in dynamic object:
So I'm not having any luck so far trying to cast a JSON string to a dynamic object. Anyone any idea how I could get this done?
Using Json.Net
dynamic dynamicObject1 = JsonConvert.DeserializeObject(json);
Console.WriteLine(dynamicObject1.Name);
Using Json.Net but deserializing into a ExpandableOBject, a type that is native to C#:
dynamic obj= JsonConvert.DeserializeObject<ExpandoObject>(yourjson);
If the target type is not specified then it will be convert to JObject type instead. Json object has json types attached to every node that can cause problems when converting the object into other dynamic type like mongo bson.

JSON.NET - Recognizing a nested array

I have this code for getting values out of a json string.
var json = #"[{""property"":""Status"",""value"":""val""}]";
var jArray = JArray.Parse(json);
foreach (JToken jToken in jArray)
{
var property = jToken.Value<string>("property");
var value = jToken.Value<string>("value");
}
This works perfect for the provided input. But in some situations the value property may contain an array.
var json = #"[{""property"":""Status"",""value"":[1,2]}]";
I'd like to check somehow if the value contains a simple value or an array. If the value is an array then bind it to a collection.
Is this possible using JSON.net ?
dynamic value = jToken["value"];
if (value is JArray)
// do something
(you could use object instead of dynamic in my example, but dynamic might be easier to work with later)

Categories