Create Json dynamically in c# - c#

I need to create a Json object dynamically by looping through columns.
so declaring an empty json object then add elements to it dynamically.
eg:
List<String> columns = new List<String>{"FirstName","LastName"};
var jsonObj = new {};
for(Int32 i=0;i<columns.Count();i++)
jsonObj[col[i]]="Json" + i;
And the final json object should be like this:
jsonObj={FirstName="Json0", LastName="Json1"};

[TestFixture]
public class DynamicJson
{
[Test]
public void Test()
{
dynamic flexible = new ExpandoObject();
flexible.Int = 3;
flexible.String = "hi";
var dictionary = (IDictionary<string, object>)flexible;
dictionary.Add("Bool", false);
var serialized = JsonConvert.SerializeObject(dictionary); // {"Int":3,"String":"hi","Bool":false}
}
}

I found a solution very similar to DPeden, though there is no need to use the IDictionary, you can pass directly from an ExpandoObject to a JSON convert:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
foo.Test = true;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
and the output becomes:
{ "FirstName":"John", "LastName":"Doe", "Active":true }

You should use the JavaScriptSerializer. That can Serialize actual types for you into JSON :)
Reference: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
EDIT: Something like this?
var columns = new Dictionary<string, string>
{
{ "FirstName", "Mathew"},
{ "Surname", "Thompson"},
{ "Gender", "Male"},
{ "SerializeMe", "GoOnThen"}
};
var jsSerializer = new JavaScriptSerializer();
var serialized = jsSerializer.Serialize(columns);
Output:
{"FirstName":"Mathew","Surname":"Thompson","Gender":"Male","SerializeMe":"GoOnThen"}

Using dynamic and JObject
dynamic product = new JObject();
product.ProductName = "Elbow Grease";
product.Enabled = true;
product.StockCount = 9000;
Console.WriteLine(product.ToString());
// {
// "ProductName": "Elbow Grease",
// "Enabled": true,
// "StockCount": 9000
// }
Or how about:
JObject obj = JObject.FromObject(new
{
ProductName = "Elbow Grease",
Enabled = true,
StockCount = 9000
});
Console.WriteLine(obj.ToString());
// {
// "ProductName": "Elbow Grease",
// "Enabled": true,
// "StockCount": 9000
// }
https://www.newtonsoft.com/json/help/html/CreateJsonDynamic.htm

Related

Serialize an anonymous JSON array without keys

I have an anonymous JSON object and I need to add a list of strings (parameter: productOptions) to it. I need to put them into a keyless JSON-array. How would I do that with anonymous types?
public static List<Product> getProductsByProductOptions(long salespartnerGroupID, string marktCode, long producttypeGroupID, long productvalueGroupID, long deviceGroupID, List<string> productOptions)
{
RestRequest request = newRestRequest("getProductsByProductOptions");
var jsonObj = new
{
input = new
{
spbgid = salespartnerGroupID,
code = marktCode,
producttypegid = producttypeGroupID,
productvaluegid = productvalueGroupID,
devicegid = deviceGroupID,
productOptions = new { item = productOptions }
},
};
IRestResponse response = GetResponseAndSerialize(jsonObj, request);
BaseProduct myDeserializedClass = JsonConvert.DeserializeObject<BaseProduct>(response.Content);
return myDeserializedClass.#return.item;
}
I need the JSON to be like this:
"input": {
"spbgid": 3797,
"code": "xxx",
"producttypegid": 5239,
"productvaluegid": 0,
"devicegid": 4030,
"productOptions": {
"item": [
"SCREEN_PROTECTOR", "REPLACEMENT"
]
}
}
I am not sure why but using the RestSharp.JsonSerializer instead of JsonConvert fixed the problem. The anonymous object seemingly works just fine.

How to convert list to expandobject key in c#?

I have a function in which i am getting data(array of objects) from db and then adding those objects of array one by one into a lit of type ExpandoObject
public async Task<List<ExpandoObject>> GetGroupWithMaxTickets(){
List<ExpandoObject> topGroupsWithMaxTickets = new List<ExpandoObject>();
dynamic ticketDetails = new ExpandoObject();
var pipeline_tickets = new BsonDocument[]{
new BsonDocument("$match",
new BsonDocument
{
{ "nsp", "/sbtjapan.com" },
{ "datetime",
new BsonDocument
{
{ "$gte", "2019-12-03T00:00:34.417Z" },
{ "$lte", "2019-12-03T24:00:34.417Z" }
} }
}),
new BsonDocument("$group",
new BsonDocument
{
{ "_id", "$group" },
{ "totalTIckets",
new BsonDocument("$sum", 1) }
}),
new BsonDocument("$project",
new BsonDocument
{
{ "_id", 0 },
{ "group", "$_id" },
{ "totalTIckets", 1 }
}),
new BsonDocument("$sort",
new BsonDocument("totalTIckets", -1)),
new BsonDocument("$limit", 5)
};
var collection = await DbService.tickets.AggregateAsync<RawBsonDocument>(pipeline_tickets, new AggregateOptions {UseCursor = true, BatchSize = 500});
await collection.MoveNextAsync();
if(collection.Current.ToList().Count > 0){
// ticketDetails = JsonConvert.DeserializeObject(collection.Current.ToJson());
// ticketDetails.group = collection.Current.ToList()[0]["group"];
// ticketDetails.totalTickets = collection.Current.ToList()[0]["totalTIckets"];
Parallel.ForEach(collection.Current.ToList(), (ticket) => {
Console.WriteLine("Ticket----"+ticket);
dynamic groupWithTickets = new ExpandoObject();
groupWithTickets = ticket;
topGroupsWithMaxTickets.Add(groupWithTickets);
});
}
return topGroupsWithMaxTickets;
}
But it throws an error like this
System.AggregateException: One or more errors occurred. (The best overloaded method match for 'System.Collections.Generic.List<System.Dynamic.ExpandoObject>.Add(System.Dynamic.ExpandoObject)' has some invalid arguments)
I want that my function must return array of objects of type List<ExpandoObject>
How can i do this in c#?
Since you have changed the question, following is the answer that should resolve your matters.
How to NOT work with ExpandoObjects
I tested this on my system and got it to reproduce the same results as you are getting. Following is the failed try:
dynamic employee = new ExpandoObject();
List<ExpandoObject> listOfEmployees = new List<ExpandoObject>();
employee = "someStrangeString";
listOfEmployees.Add(employee); // ERROR !!!!
and just as expected, i get the following error on Add.
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
HResult=0x80131500
Message=The best overloaded method match for 'System.Collections.Generic.List.Add(System.Dynamic.ExpandoObject)' has some invalid arguments
Source=
StackTrace:
Corrected way of ExpandoObject use
Following is the method that will take care of the issues with Adding it to the list.
Parallel.ForEach(collection.Current.ToList(), (ticket) =>
{
Console.WriteLine("Ticket----" + ticket);
dynamic groupWithTickets = new ExpandoObject();
groupWithTickets.users = ticket; //<---- Assign ticket to users element.
topGroupsWithMaxTickets.Add(groupWithTickets);
});
What was done to fix it?
When you are working with ExpandoObjects, you have to think of dictionary type of a deal. When you declare ExpandoObject, you have to dynamically assign the value to an element (that you define).
Example from MS site: shows the proper use of ExpandoObject
dynamic employee, manager;
employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
manager = new ExpandoObject();
manager.Name = "Allison Brown";
manager.Age = 42;
manager.TeamSize = 10;
Hopefully this resolves your issue.
It should be like this;
dynamic ticketDetails = new ExpandoObject();
ticketDetails.user = collection;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(ticketDetails);
You can simply do this:
dynamic ticketDetails = new ExpandoObject();
ticketDetails = Json(new users = JsonConvert.DeserializeObject(collection.Current.ToJson()));
For testing purposes, i used an array arr that holds one of the elements. If you need that array to be part of ExtendoObject with first element being users, you can create a Json object and set the array as value to the "users" element.
dynamic ticketDetails = new ExpandoObject();
JArray arr = new JArray();
arr.Add(#"[{""name"": ""Alex"", ""age"": 21}]");
JObject o = new JObject();
o["users"] = arr.ToString();
ticketDetails = o;
// output: { "users" : [{"name" : "Alex", "age" : 21}]}

JObject nested property

I am trying to make a json object like this with JObject:
{
"input": {
"webpage/url": "http://google.com/"
}
}
I can add properties like:
JObject job = new JObject(
new JProperty("website/url", "http://www.google.com") );
But any time I try to nest an object inside another object so I can have the parent "input" it throws an exception.
How do you make nested properties with JObject?
Probably the most straightforward way would be:
var input = new JObject();
input.Add("webpage/url", "http://google.com");
var obj = new JObject();
obj.Add("input", input);
Which gives you:
{
"input": {
"webpage/url": "http://google.com"
}
}
Another way would be:
var input = new JObject
{
{ "webpage/url", "http://google.com" }
};
var obj = new JObject
{
{ "input", input }
};
... Or if you wanted it all in one statement:
var obj = new JObject
{
{
"input",
new JObject
{
{ "webpage/url", "http://google.com" }
}
}
};
Just carry on as you are, and nest them in another level:
JObject job = new JObject(
new JProperty("website/url", "http://www.google.com") );
JObject parent = new JObject(new JProperty("input", job));
parent.ToString() now gives:
{ "input": {
"website/url": "http://www.google.com" } }

Creating JSON on the fly with JObject

For some of my unit tests I want the ability to build up particular JSON values (record albums in this case) that can be used as input for the system under test.
I have the following code:
var jsonObject = new JObject();
jsonObject.Add("Date", DateTime.Now);
jsonObject.Add("Album", "Me Against The World");
jsonObject.Add("Year", 1995);
jsonObject.Add("Artist", "2Pac");
This works fine, but I have never really like the "magic string" syntax and would prefer something closer to the expando-property syntax in JavaScript like this:
jsonObject.Date = DateTime.Now;
jsonObject.Album = "Me Against The World";
jsonObject.Year = 1995;
jsonObject.Artist = "2Pac";
Well, how about:
dynamic jsonObject = new JObject();
jsonObject.Date = DateTime.Now;
jsonObject.Album = "Me Against the world";
jsonObject.Year = 1995;
jsonObject.Artist = "2Pac";
You can use the JObject.Parse operation and simply supply single quote delimited JSON text.
JObject o = JObject.Parse(#"{
'CPU': 'Intel',
'Drives': [
'DVD read/writer',
'500 gigabyte hard drive'
]
}");
This has the nice benefit of actually being JSON and so it reads as JSON.
Or you have test data that is dynamic you can use JObject.FromObject operation and supply a inline object.
JObject o = JObject.FromObject(new
{
channel = new
{
title = "James Newton-King",
link = "http://james.newtonking.com",
description = "James Newton-King's blog.",
item =
from p in posts
orderby p.Title
select new
{
title = p.Title,
description = p.Description,
link = p.Link,
category = p.Categories
}
}
});
Json.net documentation for serialization
Neither dynamic, nor JObject.FromObject solution works when you have JSON properties that are not valid C# variable names e.g. "#odata.etag". I prefer the indexer initializer syntax in my test cases:
JObject jsonObject = new JObject
{
["Date"] = DateTime.Now,
["Album"] = "Me Against The World",
["Year"] = 1995,
["Artist"] = "2Pac"
};
Having separate set of enclosing symbols for initializing JObject and for adding properties to it makes the index initializers more readable than classic object initializers, especially in case of compound JSON objects as below:
JObject jsonObject = new JObject
{
["Date"] = DateTime.Now,
["Album"] = "Me Against The World",
["Year"] = 1995,
["Artist"] = new JObject
{
["Name"] = "2Pac",
["Age"] = 28
}
};
With object initializer syntax, the above initialization would be:
JObject jsonObject = new JObject
{
{ "Date", DateTime.Now },
{ "Album", "Me Against The World" },
{ "Year", 1995 },
{ "Artist", new JObject
{
{ "Name", "2Pac" },
{ "Age", 28 }
}
}
};
There are some environment where you cannot use dynamic (e.g. Xamarin.iOS) or cases in where you just look for an alternative to the previous valid answers.
In these cases you can do:
using Newtonsoft.Json.Linq;
JObject jsonObject =
new JObject(
new JProperty("Date", DateTime.Now),
new JProperty("Album", "Me Against The World"),
new JProperty("Year", "James 2Pac-King's blog."),
new JProperty("Artist", "2Pac")
)
More documentation here:
http://www.newtonsoft.com/json/help/html/CreatingLINQtoJSON.htm
Sooner or later you will have property with a special character. e.g. Create-Date. The hyphen won't be allowed in property name. This will break your code. In such scenario, You can either use index or combination of index and property.
dynamic jsonObject = new JObject();
jsonObject["Create-Date"] = DateTime.Now; //<-Index use
jsonObject.Album = "Me Against the world"; //<- Property use
jsonObject["Create-Year"] = 1995; //<-Index use
jsonObject.Artist = "2Pac"; //<-Property use
Simple way of creating newtonsoft JObject from Properties.
This is a Sample User Properties
public class User
{
public string Name;
public string MobileNo;
public string Address;
}
and i want this property in newtonsoft JObject is:
JObject obj = JObject.FromObject(new User()
{
Name = "Manjunath",
MobileNo = "9876543210",
Address = "Mumbai, Maharashtra, India",
});
Output will be like this:
{"Name":"Manjunath","MobileNo":"9876543210","Address":"Mumbai, Maharashtra, India"}
You could use the nameof expression combined with a model for the structure you're trying to build.
Example:
record RecordAlbum(string Album, string Artist, int Year);
var jsonObject = new JObject
{
{ nameof(RecordAlbum.Album), "Me Against The World" },
{ nameof(RecordAlbum.Artist), "2Pac" },
{ nameof(RecordAlbum.Year), 1995 }
};
As an added benefit to removing the "magic string" aspect - this also will give you a little bit of refactor-ability. You can easily rename any given property name for the record and it should update the value returned by the nameof() expression.
You can use Newtonsoft library and use it as follows
using Newtonsoft.Json;
public class jb
{
public DateTime Date { set; get; }
public string Artist { set; get; }
public int Year { set; get; }
public string album { set; get; }
}
var jsonObject = new jb();
jsonObject.Date = DateTime.Now;
jsonObject.Album = "Me Against The World";
jsonObject.Year = 1995;
jsonObject.Artist = "2Pac";
System.Web.Script.Serialization.JavaScriptSerializer oSerializer =
new System.Web.Script.Serialization.JavaScriptSerializer();
string sJSON = oSerializer.Serialize(jsonObject );

Using JSON.NET to add a boolean property

I have this JSON data
{
"extensions": {
"settings" : {
"extension1": {
"property1": "value 1",
"property2": "value 2"
}
}
}
}
my goal is to add a new boolean property using JSON.NET to look like this
{
"extensions": {
"settings" : {
"extension1": {
"property1": "value 1",
"property2": "value 2",
"bool_property": true
}
}
}
}
I only have this code and I'm stuck with AddAfterSelf and AddBeforeSelf
string pref = "path_of_the_preferences_file";
string _pref = string.empty;
using (StreamReader reader = new StreamReader(pref, Encoding.UTF8))
{
_pref = reader.ReadToEnd();
}
// REFORMAT JSON.DATA
JObject json = JObject.Parse(_pref);
var extension1 = json["extensions"]["settings"]["extension1"];
How do I insert the new boolean property "bool_property" ?
Thanks
A JObject is essentially a dictionary. Just get a reference to the object you wish to add the property to and add it.
var propertyName = "bool_property";
var value = true;
var obj = JObject.Parse(json);
var extension1 = obj.SelectToken("extensions.settings.extension1") as JObject;
if (extension1 != null)
{
extension1[propertyName] = value;
}
If you're targeting .NET 4 and up, you know the structure of the json and the name of the property you wish to add, you can use dynamic here.
var value = true;
dynamic obj = JObject.Parse(json);
obj.extensions.settings.extension1.bool_value = value;
You can even mix and match.
var propertyName = "bool_property";
var value = true;
dynamic obj = JObject.Parse(json);
obj.extensions.settings.extension1[propertyName] = value;
Deserialize your JSON, add a property and serialize it back into a string.
dynamic sourceJson = JsonConvert.DeserializeObject(json, typeof(object));
sourceJson.extensions.settings.extension1.bool_property = false;
var modifiedJson = JsonConvert.SerializeObject(sourceJson, Formatting.Indented);
I got it
string pref = "path_of_the_preferences_file";
string _pref = string.empty;
using (StreamReader reader = new StreamReader(pref, Encoding.UTF8))
{
_pref = reader.ReadToEnd();
}
// REFORMAT JSON.DATA
JObject json = JObject.Parse(_pref);
var extension1 = json["extensions"]["settings"]["extension1"];
var a = extension1.Children();
JProperty cond_it = null;
foreach (var b in a)
{
if (b.ToString().ToLower().Contains("cond_it"))
{
cond_it = (JProperty)b;
break;
}
}
if (cond_it != null)
{
var b = cond_it.Value.SelectToken("location").Parent;
b.AddAfterSelf(new JProperty("blacklist", true));
}

Categories

Resources