How do I merge multiple json objects - c#

I use different urls get similar json data.
So that I can get more information in the same model
It has trouble me for a long time
i tried to use json.net for a single list.
string url1= "https://apt.data2.com";
string url2= "https://apt.data1.com";
var json1= webClient.DownloadString(url1);
var json2= webClient.DownloadString(url2);
These calls return multiple json objects with the same structure
{
data: [
{
created_time: "1457332172",
text: "什麼東西",
from: {
username: "d86241",
profile_picture: "https://scontent.cdninstagram.com/t51.2885-19/s150x150/11371189_421316874725117_327631552_a.jpg",
id: "397355082",
full_name: "Jhao-wei Hvang"
},
id: "1200511729352353899"
}
]
}
and
{
data: [
{
created_time: "1111",
text: "hi",
from: {
username: "22",
profile_picture: "",
id: "ss",
full_name: "Hvang"
},
id: "1200511352353899"
}
]
}
I want to combine these objects to produce
{
data:[
{
created_time:"1234"
text:...
....
......
},
id:1234....
]
data:[
{
created_time:"4567"
text:....
....
......
},
id:4567....
]
}
How do I merge these into a single json object?
#foreach (var item in Model)
     {
# Item.text
    }

var jObject1 = // Your first json object as JObject
var jObject2 = // Your second json object as JObject
jObject1.Merge(jObject2);

Related

Add a list in an existing JSON value

So I have below call to a method where my argument is a json string of this type
var jsonWithSearchData = await querySearchData(jsonOut);
jsonOut ->
[
{
"data": {
"_hash": null,
"kind": "ENY",
"id": "t123",
"payload": {
"r:attributes": {
"lok:934": "#0|I"
},
"r:relations": {
"lok:1445": "15318",
"lok:8538": "08562"
},
"r:searchData": "",
"r:type": [
"5085"
]
},
"type": "EQT",
"version": "d06"
}
}
]
The querySearchData() returns me two list something like this :["P123","P124","P987"] and ["Ba123","KO817","Daaa112"]
I want to add this list in my r:searchData key above. The key inside my searchData i.e. r:Porelation and ClassA and ClassB remains static. So I would like my searchData in my input Json to finally become something like this.
"r:searchData": {
"r:Porelation":{
"ClassA": ["P123","P124","P987"],
"ClassB": ["Ba123","KO817","Daaa112"]
}
},
How can I do this? What I tried:
JArray jfinObject = JArray.Parse(jobjects);
jfinObject["r:searchData"]["r:relations"]["ClassA"] = JArray.Parse(ListofCode.ToString());
And I get below error:
System.Private.CoreLib: Exception while executing function: Function1.
Newtonsoft.Json: Accessed JArray values with invalid key value:
"r:searchData". Int32 array index expected.
There are a few ways you can add a node/object/array to existing json.
One option is to use Linq-to-Json to build up the correct model.
Assuming you have the json string described in your question, the below code will add your desired json to the r:searchData node:
var arr = JArray.Parse(json); // the json string
var payloadNode = arr[0]["data"]["payload"];
// use linq-to-json to create the correct object
var objectToAdd = new JObject(
new JProperty("r:Porelation",
new JObject(
new JProperty("r:ClassA", array1),
new JProperty("r:ClassB", array2))));
payloadNode["r:searchData"] = objectToAdd;
where array1 and array2 above could come from a linq query (or just standard arrays).
// Output:
{
"data": {
"_hash": null,
"kind": "ENY",
"id": "t123",
"payload": {
"r:attributes": {
"lok:934": "#0|I"
},
"r:relations": {
"lok:1445": "15318",
"lok:8538": "08562"
},
"r:searchData": {
"r:Porelation": {
"r:ClassA": [
"P123",
"P456"
],
"r:ClassB": [
"Ba123",
"Ba456"
]
}
},
"r:type": [
"5085"
]
},
"type": "EQT",
"version": "d06"
}
}
Online demo
Another option is to create the json from an object, which could be achieved using JToken.FromObject(). However, this will only work if you have property names which are also valid for C# properties. So, this won't work for your desired property names as they contain invalid characters for C# properties, but it might help someone else:
// create JToken with required data using anonymous type
var porelation = JToken.FromObject(new
{
ClassA = new[] { "P123", "P456" }, // replace with your arrays here
ClassB = new[] { "Ba123", "Ba456" } // and here
});
// create JObject and add to original array
var newObjectToAdd = new JObject(new JProperty("r:Porelation", porelation));
payloadNode["r:searchData"] = newObjectToAdd;

JObject parse returns extra curly braces

I have a variable projectData that contains a valid json string that is stored in a database.
After doing the following:
JObject obj = new JObject();
obj = JObject.Parse(projectData);
Instead of getting
{
"devices": {
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
}
I get this instead:
{{
"devices": {
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
}}
So basically an aditional { and } were added to my json string.
I have also tried the following:
obj = JsonConvert.DeserializeObject<JObject>(projectData);
and it didnt work.
Why is this a problem to me?
I want to iterate over the obj["devices"] array, and when I do the following
foreach(var d in obj["devices"])
It simply doesnt work because of the double curly braces.
Is there a solution to my problem?
Thank you
{
"devices": {
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
}
Your json shows devices as a json object and not an array. You cannot iterate over it with a for loop.
You can access the data by parsing it first and then accessing the properties by using the [] brackets.
var obj = JObject.Parse(jsonString);
Console.WriteLine(obj["devices"]["device_A"]["id"].Value<string>());
//prints
12345
// To Loop through multiple devices... you can use this.
foreach (var device in ((JObject)obj["devices"]).Properties())
Console.WriteLine(obj["devices"][device.Name]["id"]);
Also, when you are using the debug mode, the watch or locals will show {{ }} because the braces are escaped.
Array version of Json
If your json looked like below, then you can use the for loop to access the elements of the JArray.
{
"devices": [
{
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
]
}
with the above json, you can use the for loop in the following way,
var obj = JObject.Parse(json);
foreach (var device in obj["devices"])
Console.WriteLine(device["device_A"]["id"]);
// Prints
12345

Given a JSON value, how do I get the parent's sibling value?

I have a .NET Core 3.1 C# application reading the following JSON doc:
{
"info": {
"_postman_id": "b"
},
"item": [
{
"name": "GetEntityById via APIM",
"item": [
{
"name": "Call 1",
"url": {
"raw": "urlforcall1"
}
},
{
"name": "Call 2",
"url": {
"raw": "urlforcall2"
}
}
]
}
]
}
I want to select the value for each item\item\name and each item\item\url\raw.
So, I'd like to end up with "Call 1":"urlforcall1" and "Call 2":"urlforcall2".
I've been playing around and can grab the value from the raw token with the following:
var jObject = JObject.Parse(jsonString);
var urls = jObject.SelectTokens("..raw");
How can I grab the value from its parent's sibling, name?
I hope this code will help you
using Newtonsoft.Json.Linq;
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
string json = #"
{
'info': {
'_postman_id': 'b'
},
'item': [
{
'name': 'GetEntityById via APIM',
'item': [
{
'name': 'Call 1',
'url': {
'raw': 'urlforcall1',
}
},
{
'name': 'Call 2',
'url': {
'raw': 'urlforcall2',
}
}
]
}
]
}";
dynamic d = JObject.Parse(json);
foreach(var item in d.item)
{
foreach(var innerItem in item.item)
{
Console.WriteLine($"'{innerItem.name}' : '{innerItem.url.raw}'");
}
}
}
}
}
Can be tested here https://dotnetfiddle.net/xDr90O
To answer your question directly, if you have a JToken you can navigate upward from there using the Parent property. In your case you would need to use it four times to get to the level you want:
The parent of the JValue representing the call URL string is a JProperty with the name raw
The parent of that JProperty is a JObject
The parent of that JObject is a JProperty with the name url
The parent of that JProperty is a JObject, which also contains the name property
From there you can navigate back down using indexer syntax to get the value of name.
So, you would end up with this:
var jObject = JObject.Parse(jsonString);
foreach (JToken raw in jObject.SelectTokens("..raw"))
{
string callName = (string)raw.Parent.Parent.Parent.Parent["name"];
string urlForCall = (string)raw;
}
You may flatten inner item array using SelectMany method into one sequence (since outer item is also an array), then get name and raw values directly by key
var jObject = JObject.Parse(jsonString);
var innerItems = jObject["item"]?.SelectMany(t => t["item"]);
foreach (var item in innerItems)
{
var name = item["name"];
var raw = item["url"]?["raw"];
}

Json nested objects deserialization

I would like to dynamically create c# object based on the the consumed Json. I do not care about this json but simply would like pick out properties that I need.
I dont know if its best practice to use dynamic keyword and based on the created object I can create a whole new json structure.
How can I desearilize nested objects. Example json:
{
'name': 'James',
'Profile': {
'body': {
'id': 'Employee1',
'type': 'Employee',
'attributes': {
props...
},
'job': {
props..
},
'team': [],
},
}
Here is a simple attempt.
var test = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine(test.ToString());
I can create object list however when I begin Parent/Child objects I cant seem to get it to work.
Below JSON works fine as an output:
'body': {
'id': 'Employee1',
'type': 'Employee',
'attributes': {
props...
},
'job': {
props..
},
'team': [],
}
Desired Output
{
'name': 'James',
'Profile': {
'body': {
'id': 'Employee1',
'type': 'Employee',
'attributes': {
props...
},
'job': {
props..
},
'team': [],
},
'Profile': {
'body': {
'id': 'Employee2',
'type': 'Employee',
'attributes': {
props...
},
'job': {
props..
},
'team': [],
}
}
How can I deserialize nested objects?
You can use the json class with following this line of code
dynamic data = Json.Decode(json);
You can use JsonConvert:
dynamic myNewObject = JsonConvert.DeserializeObject(json);
And then, you can access json properties like this:
myNewObject.Profile.body.id
No repro. The string is already deserialized. test contains the entire graph. The expected output is produced as long as a valid JSON string is used :
This snippet :
var json=#"{
'name': 'James',
'Profile': {
'body': {
'id': 'Employee1',
'type': 'Employee',
'attributes': {
'a':3
},
'job': {
'a':3
},
'team': [],
},
}";
var x=JsonConvert.DeserializeObject<object>(json);
Console.WriteLiine(x.ToString());
Produces :
{
"name": "James",
"Profile": {
"body": {
"id": "Employee1",
"type": "Employee",
"attributes": {
"a": 3
},
"job": {
"a": 3
},
"team": []
}
}
}
From the comments though, it looks like the actual JSON string isn't a valid JSON string and throws an exception :
I get Newtonsoft.Json.JsonReaderException: 'Additional text encountered after finished reading JSON content: ,. Path '', line 21, position 13.'
This error points to the actual location in the JSON string that caused the problem. Perhaps there's an extra character there? Perhaps the text contains multiple JSON strings instead of one? The following string is not valid JSON - JSON can't have more than one root objects :
{ "a":"b"}
{ "c":"d"}
Logging tools, event processing and analytic software though store multiple JSON strings per file this way because it only needs an append operation, doesn't require parsing the entire text to produce results and makes partitioning easier. That's still invalid JSON though that has to be read and processed one line at a a time.
You many find this described as "streaming JSON", precisely because you can process the data in a streaming fashion. Instead of loading and parsing a 100MB event file, you can load and process a single line at a time eg:
IEnumerable<string> lines=File.ReadLines(pathToBigFile);
foreach(var line in lines)
{
var myObject=JsonConvert.DeserializeObject<someType>(line);
//do something with that object
}
File.ReadLines returns an IEnumerable<string> that only loads a single line on each iteration. Instead of loading the entire 100MB file, only one line is loaded and parsed each time.

Serialize list of dictionaries into accepted DataTable Ajax object

I have a web application in which I'm retrieving some data into bootstrap table, what i want to do now is to use jQuery DataTable instead of the current as it has too much useful features.
Currently I'm retrieving the data from the server side using OOP approach, where a class object represents a data row in a particular table, and this object includes a dictionary which stores column names and values.
What I'm doing now is that I'm retrieving these class objects and append each dictionary of each object in a List<Item> and then serialize this list using JavaScriptSerializer object, and this object returns the following JSON format:
[
{
"slno":"2",
"status_message":"Lights still flashing",
"crm_services_id":"1", "subject_id":"Lights are flashing",
"severity_id":"5",
"user_id":"husain.alhamali",
"status_id":"1"
},
{
"slno":"3",
"status_message":"lights working fine",
"crm_services_id":"2",
"subject_id":"Lights are flashing",
"severity_id":"3",
"user_id":"husain.alhamali",
"status_id":"2"
}
]
When i tried to use this object to fill my DataTable AJAX I've got an error says:
Invalid JSON response
I saw some examples of a valid JSON response that is acceptable to a DataTable which is as follow:
{
"data": [
[
"Tiger Nixon",
"System Architect",
"Edinburgh",
"5421",
"2011/04/25",
"$320,800"
],
[
"Garrett Winters",
"Accountant",
"Tokyo",
"8422",
"2011/07/25",
"$170,750"
]
}
Now my question is is there any tool or plugin that could re-format my JSON string into an acceptable format like the one above?
With this HTML:
<table id="example"></table>
This JS will create a table:
var data = [{
"slno": "2",
"status_message": "Lights still flashing",
"crm_services_id": "1",
"subject_id": "Lights are flashing",
"severity_id": "5",
"user_id": "husain.alhamali",
"status_id": "1"
}, {
"slno": "3",
"status_message": "lights working fine",
"crm_services_id": "2",
"subject_id": "Lights are flashing",
"severity_id": "3",
"user_id": "husain.alhamali",
"status_id": "2"
}];
function getColumns(){
for(var i = 0; i < data.length; i++){
let columnsArray = [];
var keys = Object.keys(data[i]);
for(k in Object.keys(data[i])){
if(data[i].hasOwnProperty(keys[k])){
columnsArray.push({
"data":keys[k]
});
}
}
return columnsArray;
}
}
$(document).ready(function() {
var table = $('#example').DataTable({
"columns": getColumns(),
"data": data
});
});
Working example. Hope that helps.
dataTable require json data in return from ajax response having following keys
1. data
2. draw
3. recordsTotal
4. recordsFiltered
Use this:
var data = list.Select(u => u.GetType()
.GetProperties()
.Select(p => p.GetValue(u, null)));
example
public class User
{
public int userId { get; set; }
public string name { get; set; }
}
public class Programm
{
static void Main()
{
var list = new List<User>();
list.Add(new User
{
userId = 1,
name = "name 1",
});
list.Add(new User
{
userId = 2,
name = "name 2",
});
var data = list.Select(u => u.GetType()
.GetProperties()
.Select(p => p.GetValue(u, null)));
Console.WriteLine(new JavaScriptSerializer().Serialize(new
{
data = data
}));
}
}
result
{
"data" : [
["1", "name 1"],
["2", "name 2"]
]
}

Categories