How can I merge two JObject? [duplicate] - c#

This question already has answers here:
Merge two Json.NET arrays by concatenating contained elements
(3 answers)
Closed 7 years ago.
I have a first json:
{
"data": [{
"id": "id1",
"field": "field1"
}],
"paging": {
"prev": "link1",
}
}
and a second one:
{
"data": [{
"id": "id2",
"field": "field2"
}],
"paging": {
"prev": "link2",
}
}
and I want to merge/union the two Data array, such as:
{
"data": [{
"id": "id1",
"field": "field1"
},
{
"id": "id2",
"field": "field2"
}]
}
(I don't care about about paging right now).
How can I do it quick and easy? This is my try:
var final = JsonConvert.SerializeObject(new { data = json1["data"].Union(json2["data"]) }, Newtonsoft.Json.Formatting.Indented).ToString();
but an Exception is raised: 'Newtonsoft.Json.Linq.JArray' does not contains a definition of 'Union'

Newtonsoft.Json now supports merging objects (old link):
var dataObject1 = JObject.Parse(#"{
""data"": [{
""id"": ""id1"",
""field"": ""field1""
}],
""paging"": {
""prev"": ""link1"",
}
}");
var dataObject2 = JObject.Parse(#"{
""data"": [{
""id"": ""id2"",
""field"": ""field2""
}],
""paging"": {
""prev"": ""link2"",
}
}");
var mergeSettings = new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Union
};
// method 1
(dataObject1.SelectToken("data") as JArray).Merge(dataObject2.SelectToken("data"), mergeSettings);
// method 2
//dataObject1.Merge(dataObject2, mergeSettings);
var mergedArray = dataObject1.SelectToken("data") as JArray;
Console.WriteLine(mergedArray.ToString(Formatting.None));
(checked with brain-compiler ;) )

JArray dataOfJson1=json1.SelectToken("data");
JArray dataofJson2=json2.SelectToken("data");
foreach(JObject innerData in dataofJson2)
{
dataOfJson1.Add(innerData);
}

For those that (like me) cannot use the new JSON.net library.
The following method is what I use.
public static JObject mergeJsonObjects(List<JObject> objects) {
JObject json = new JObject();
foreach(JObject JSONObject in objects) {
foreach(var property in JSONObject) {
string name = property.Key;
JToken value = property.Value;
json.Add(property.Key, property.Value);
}
}
return json;
}
The method takes an list of JObjects and returns a single JObject, simpel and effective.

A possible solution could be:
class Container
{
public List<IdField> data{get;set;}
}
class IdField
{
public string id{get;set;}
public string field{get;set;}
}
string s1 = "{ \"data\": [{ \"id\": \"id1\", \"field\": \"field1\" }], \"paging\": { \"prev\": \"link1\", } }";
string s2 = "{ \"data\": [{ \"id\": \"id2\", \"field\": \"field2\" }], \"paging\": { \"prev\": \"link2\", } }";
var d1 = JsonConvert.DeserializeObject<Container>(s1);
var d2 = JsonConvert.DeserializeObject<Container>(s2);
d1.data.AddRange(d2.data);
var result = JsonConvert.SerializeObject(d1);

Related

Why does JSON.Net modify the original JObject?

I'm trying to understand why JSON.Net will modify the original JObject (formSchema) in two cases below where I'm adding JArray and JObject
to objects I've defined as vars.
I assume the two vars I created were standalone objects in their own right but it appears they are not.
In the first case, requiredItems is a JArray var, in which I want to add the token "certification" to formSchema, but I've placed the Add method
on requiredItems. Not formSchema.
In the second case, I add certifyProperty to formSchema using the Add method on consentProps. The property handily gets added to formSchema
without a direct reference to it.
Why is this? Are they linked in memory? Where in the JSON.Net docs is this explained? I cannot find it.
namespace JSONProps
{
class Program
{
static void Main(string[] args)
{
string jsonSchema = #"
{
""jsonSchema"": {
""type"": ""object"",
""title"": ""a title"",
""properties"": {
""consent"": {
""type"": ""object"",
""title"": ""Consent of Applicant"",
""required"": [
""applicantConsent""
],
""properties"": {
""applicantConsent"": {
""type"": ""boolean"",
""title"": ""I give my Consent"",
},
}
}
}
}
}
";
// First case
var formSchema = JObject.Parse(jsonSchema);
var requiredProps = formSchema["jsonSchema"]["properties"]["consent"]["required"] as JArray;
requiredProps.Add("certification");
// Second case
var consentProps = formSchema["jsonSchema"]["properties"]["consent"]["properties"] as JObject;
var certifyProperty = JObject.Parse(#" { ""type"" : ""boolean"", ""title"" : ""This is true."" } ");
consentProps.Add("certification", certifyProperty);
Console.WriteLine(formSchema.ToString());
}
}
}
$ dotnet run
{
"jsonSchema": {
"type": "object",
"title": "a title",
"properties": {
"consent": {
"type": "object",
"title": "Consent of Applicant",
"required": [
"applicantConsent",
"certification"
],
"properties": {
"applicantConsent": {
"type": "boolean",
"title": "I give my Consent"
},
"certification": {
"type": "boolean",
"title": "This is true."
}
}
}
}
}
}

How to update property value in JSON string?

Below is my JSON:
[
{
"name": "Node-1",
"flag": true,
"myObj": {
region: {
info: {
name: null,
infoFlag: false,
}
}
},
"nodes": [
{
"name": "Node-1-1",
"flag": true,
"myObj": {
region: {
info: {
name: "abc",
infoFlag: false,
}
}
},
"nodes": [
{
"name": "Node-1-1-1",
"flag": true,
"myObj": {
region: {
info: {
name: "xyz",
infoFlag: false,
}
}
},
"nodes": [
]
}
]
}
]
}
]
I want to update two properties of my above JSON string with following rule :
Flag : I want to blindly update this property to false.
infoFlag: If name property of info is null then I want to update infoFlag to true else false if it is not null.
So after updating my JSON with these rules I want to have that JSON as a string.
Note: I don't want to deserialize and then update property based on above two rules as because my JSON has lots of properties for which I don't want to create classes, so I am looking for something which will work without deserializing with class.
This is how I am trying to do it:
string json = "MyJson";
var temp = JArray.Parse(json);
temp.Descendants()
.OfType<JProperty>()
json = temp.ToString();
But here I am not getting as how to traverse my JSON recursively; as you can see I have recursive structure like below :
Node-1
Node-1-1
Node-1-1-1
Json.NET allows you to treat its internal objects representing the JSON content as dynamic, which makes the task in question no harder than using regular typed objects.
The only kind of tough problem is the recursive object structure (the nodes array), but that's not a JSON or dynamic specific problem, and can be solved in many ways - the obvious recursive method or with my preferable tree flattening enumeration (the Expand method from my answer to How to flatten tree via LINQ?).
With that being said, the solution could be like this:
var array = JArray.Parse(json);
var nodes = array.Cast<dynamic>().Expand(x => x.nodes);
foreach (var node in nodes)
{
node.flag = true;
var info = node.myObj.region.info;
info.infoFlag = (info.name == null);
}
var newJson = array.ToString();
If I have understood your needs this code is pretty verbose and not so elegant but works:
JArray temp = JArray.Parse(json);
foreach (JToken tk in temp.Descendants())
{
if (tk.Type == JTokenType.Property)
{
JProperty p = tk as JProperty;
if (p.Name == "flag")
{
if ((bool)p.Value.ToObject(typeof(bool)) == true)
p.Value = false;
}
if ((p.Name == "info") && p.HasValues)
{
bool flag = false;
foreach (JToken tkk in p.Descendants())
{
if (tkk.Type == JTokenType.Property)
{
JProperty pp = tkk as JProperty;
if ((pp.Name == "name") && (pp.Value.Type == JTokenType.Null))
{
flag = true;
}
if ((pp.Name == "infoFlag"))
{
pp.Value = (flag == true) ? true : false;
}
}
}
}
}
}
json = temp.ToString();
This is the resulting output:
[
{
"name": "Node-1",
"flag": false,
"myObj": {
"region": {
"info": {
"name": null,
"infoFlag": true
}
}
},
"nodes": [
{
"name": "Node-1-1",
"flag": false,
"myObj": {
"region": {
"info": {
"name": "abc",
"infoFlag": false
}
}
},
"nodes": [
{
"name": "Node-1-1-1",
"flag": false,
"myObj": {
"region": {
"info": {
"name": "xyz",
"infoFlag": false
}
}
},
"nodes": []
}
]
}
]
}
]

There is no argument that corresponds to the required formal parameter

This is probably not the best way to be doing this but it's the best I know how to do with c#. I'm trying to create a dictionary and then convert it to json later. Right now I"m just trying to get the dictionary to match what I want in the json format later. Here is what I have so far:
`Dictionary<Dictionary<string, string>, Dictionary<string, List<List<Decimal>>>> testDict = new Dictionary<Dictionary<string, string>, Dictionary<string, List<List<Decimal>>>>() {
new Dictionary<string, string>() {
{ "test", "test" }
}
};`
This is giving me the following error:
There is no argument that corresponds to the required formal parameter
I don't know what could be causing this and any help would be great, thanks!
Here is the json structure I'm trying to replicate:
[
{
"target": "1",
"datapoints": [
[
67.0,
1491609600.0
]
]
},
{
"target": "2",
"datapoints": [
[
54.0,
1491091200.0
],
[
65.0,
1491177600.0
],
[
69.0,
1491609600.0
],
[
65.0,
1491696000.0
],
[
54.0,
1491868800.0
],
[
63.0,
1491955200.0
],
[
64.0,
1492214400.0
],
[
57.0,
1492732800.0
],
[
72.0,
1492819200.0
],
[
50.0,
1493337600.0
],
[
63.0,
1493424000.0
]
]
},
]
Ok, not the answer to your question, but it will help, is the correct structure for your JSON:
public class TargetClass
{
public string target{ get; set; }
public List<double[]> datapoints{ get; set; }
}
That's the base class. If you want to deserialize what you have in JSON you will do something like this (assuming you are using Newtonsoft Json, else change to the library you use):
var data = Newtonsoft.Json.JsonConvert.DeserializeObject<TargetClass[]>(theString);
And to serialize you would create something like this:
var items = new List<TargetClass>();
var target = new TargetClass{ target = "1", datapoints = new List<double[]>{ new double[]{ 67.0, 1491609600.0 } };
items.Add(target);
var ser = Newtonsoft.Json.JsonConvert.SerializeObject(items);
Using anonymous types you can create complex object hierarchies almost as easy as writing plain JSON:
var obj = new[] {
new {
target = "1",
datapoints = new [] {
new [] {
67.0,
1491609600.0
}
}
},
new {
target = "2",
datapoints = new [] {
new [] {
54.0,
1491091200.0
},
new [] {
65.0,
1491177600.0
},
}
}
};
var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Demo: https://dotnetfiddle.net/jk8gho
If subcollections in this object are a subject to expansion, these collections should better be explicitly defined as List<dynamic>. Strictly speaking this dynamic is not necessary and explicit types may be used instead, but using dynamic simplifies the definition.
var obj = new List<dynamic> {
new {
target = "1",
datapoints = new List<dynamic> {
new [] {
67.0,
1491609600.0
}
}
},
new {
target = "2",
datapoints = new List<dynamic> {
new [] {
54.0,
1491091200.0
},
new [] {
65.0,
1491177600.0
},
}
}
};
var target2 = obj.Where(t => t.target == "2").Single();
target2.datapoints.Add(new [] {
64.0,
1492214400.0
});
target2.datapoints.Add(new[] {
57.0,
1492732800.0
});
var target3 = new {
target = "3",
datapoints = new List<dynamic> { }
};
target3.datapoints.Add(new[] {
72.0,
1492819200.0
});
obj.Add(target3);
var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Demo: https://dotnetfiddle.net/d4ZUH8

c# NewtonJson Jarray check null/empty error

How we can check a json array is null or emty?
Json:
{
"productList": [
{
"id": 2440,
"serviceStatus": 1,
"listOfBillProductsExtras": [
{
"id": 2441,
"amount": 1,
"balance": 2,
}
],
"deskName": "Desk 1",
"onlyTime": "15:25"
},
{
"id": 2441,
"serviceStatus": 1,
"listOfBillProductsExtras": [ ],
"deskName": "Desk2",
"onlyTime": "15:27"
}
]
}
I try
JArray productList = JArray.Parse(content["productList"].ToString());
but it didn't work. (There was exp. Null Referance ) So, I want to check listOfBillProductsExtras array is null or empty. If not empty I will get the id, amount, balance.
Parse the Json object to jArray:
public ActionResult Method(object[] data)
{
var productList = Json.ParseJsonObjectToJArray(data, "productList");
if(jArray.Count > 0)
{
}
}
public class Json
{
public static JArray ParseJsonObjectToJArray(object[] data, string objectName)
{
dynamic jObject = JObject.Parse(data[0].ToString());
var info = jObject[objectName];
return info;
}
}
This should work
var found = JObject.Parse(json).SelectToken("productList[0].listOfBillProductsExtras[0].id");
where json is your input string.
found variable can be checked for null value.

How to properly deserialize and iterate over an array of JSON objects

In my app, I'm getting some data in a string format, which I'm converting to json:
string stringValue = System.Text.Encoding.Default.GetString(message.Value);
var jsonValue = JsonConvert.DeserializeObject(stringValue);
The resulting json string looks like this:
[
{
"LOCATION_ID": 2800,
"CITY": "Sao Paulo"
},
{
"LOCATION_ID": 1700,
"CITY": "Seattle"
},
{
"LOCATION_ID": 2300,
"CITY": "Singapore"
},
{
"LOCATION_ID": 1600,
"CITY": "South Brunswick"
},
{
"LOCATION_ID": 1500,
"CITY": "South San Francisco"
},
{
"LOCATION_ID": 1400,
"CITY": "Southlake"
},
{
"LOCATION_ID": 2600,
"CITY": "Stretford"
},
{
"LOCATION_ID": 2200,
"CITY": "Sydney"
}
]
What syntax can I use to iterate over this json array, and print out one json object at a time?
What syntax can I use to iterate over this json array, and print out
one json object at a time?
Define a model:
public class MyModel
{
public int LOCATION_ID { get; set; }
public string CITY { get; set; }
}
and then deserialize to this model:
var models = JsonConvert.DeserializeObject<IList<MyModel>>(stringValue);
and now you are free to iterate with standard C# iteration constructs like the foreach keyword:
foreach (MyModel model in models)
{
Console.WriteLine(model.LOCATION_ID);
Console.WriteLine(model.CITY);
}
The easiest way is to use dynamics as follows.
Note, this method reduces code footprint and is more readable the alternative approaches:
var json = #"[
{
'LOCATION_ID': 2800,
'CITY': 'Sao Paulo'
},
{
'LOCATION_ID': 1700,
'CITY': 'Seattle'
}
]";
dynamic parsedArray = JsonConvert.DeserializeObject(json);
foreach (dynamic item in parsedArray)
Debug.WriteLine($"Location ID: {item.LOCATION_ID} City: {item.CITY}");
Darin Dimitrov is spot on answer.
Another alternative, if you don't really want strongly model, is using Dictionary and its qualities.
var jsonObj = JsonConvert.DeserializeObject<Dictionary<string, string>[]>(stringValue);
foreach (var obj in jsonObj)
{
Console.WriteLine("{0}: {1}", obj["LOCATION_ID"], obj["CITY"]);
}

Categories