How to create json dynamically? - c#

I need to create a json dynamically using class. For example following is my json "{'createdDate':['2019-07-20T05:53:28','2019-07-20T05:53:28']}". The class i need is
public class Json
{
public string Key {get;set;}
public List<string> value {get;set;}
}
Creating object and assigning value
var JsonObj = new Json();
JsonObj.key = "createdDate";
JsonObj.Add("2019-07-20T05:53:28");
JsonObj.Add("2019-07-20T05:53:28");
The above class is for single key value pair. But the problem is the key and values are dynamic.may be the key value pairs single or multiple. How can i solve the problem. can anyone try to help me.

I think your problem starts with your nomenclature. Your class is not json, it's merely a list with a name. All you need to do is create your named list, and then serialise it to json using, for example, Newtonsoft.Json. Here's a bit of code :
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ConsoleApp1
{
public class Program
{
public static void Main()
{
NamedList list = new NamedList();
list.Key = "createdDate";
list.Value.Add( "2019-07-20T05:53:28" );
list.Value.Add( "2019-07-20T05:53:29" );
string jsonString = JsonConvert.SerializeObject( list );
}
}
public class NamedList
{
public string Key { get; set; }
public List<string> Value { get; set; }= new List<string>();
}
}

Related

C# Loop trough every property in class

I've made a class containing everything from the json file.
Now I want to loop trough every object within this object so I can for fill the application with those values.
I want to scroll trough every CM0xx and use that description:
I hope my goal is clear with that screenshot.
I know that I have to do something like
foreach(CM0XX step in Stepsss)
but that simply wont work.
If making a list<string[]> for it is easier from a json but im clueless for the solution.
this is the code I have now. And the json file ive converted is generated so that should be fine.
string testdata = File.ReadAllText(Application.StartupPath + "\\TestData\\SSH.json");
Root JsonDecoded = JsonConvert.DeserializeObject<Root>(testdata);
testSteps Stepsss = JsonDecoded.SmartShoulder.TestSteps;
foreach (testSteps step in Stepsss)
{
}
this is part of the json. there are alot more CM012
public class CM181
{
public string Name;
public string description;
public string minValue;
public string maxValue;
public string unit;
public string instructions;
public string prerequisites;
}
public class Root
{
public kkkk kk;
}
public class kkkk
{
public string preset;
public testSteps TestSteps;
}
public class testSteps
{
public CM011 CM011;
}
You could use reflection to loop through the names and the values. If you just need the items under TestSteps, this should work. If you need a full hierarchy, that is a bit more involved. Here is an example below and the fiddle to it:
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
var record = new Root()
{
Foo = "foo",
Bar = "bar"
};
PropertyInfo[] rootProperties = typeof(Record).GetProperties();
foreach (PropertyInfo property in rootProperties)
{
var value = property.GetValue(record);
Console.WriteLine(property.Name + " - " + value);
}
}
}
public class Root
{
public string Foo {get;set;}
public string Bar {get;set;}
}
Making a class to deserialize to is generally done to avoid the need to loop through all the properties. You've defined all the properties in the class, so you can just use them. It's a lot of overhead to use reflection to put all the values into a class, then again using reflection to pull them back out. That's why Newtonsoft has JToken/JObject/JArray classes.
using Newtonsoft.Json.Linq;
...
// parse your JSON
var jo = JObject.Parse(jsonString);
// go through all properties
// just for an example, I put them all in a dictionary
var dict = new Dictionary<String, JToken>()
foreach( JProperty p in jo.Properties() ) {
dict.Add(p.Name, p.Value)
}
Now, each Value is a JToken, which could actually be another JObject, or a JArray or just a simple token. You can check JToken.Type to see what type the property really has, and do something logical accordingly.

XmlArray with multiple names

I've searched for hours and found similar results but not for this specific scenario. Consider the following XML file.
<root>
<largeImages>
<largeImage>
<url>./imageLarge.jpg</url>
<height>480</height>
<width>640</width>
</largeImage>
</largeImages>
<smallImages>
<smallImage>
<url>./imageSmall.jpg</url>
<height>240</height>
<width>320</width>
</smallImage>
</smallImages>
</root>
What I'm trying to do is deserialize this into a single array of images instead of 2 arrays.
public class root {
[XmlArray("largeImages")]
[XmlArrayItem("largeImage")]
public image[] largeImages { get; set; }
[XmlArray("smallImages")]
[XmlArrayItem("smallImage")]
public image[] smallImages { get; set; }
}
This class gets me 2 arrays. root.largeImages and root.smallImages. Since my application doesn't care about large or small images I'd like to deserialize into the single array root.images. I've tried variations of XmlArray, XmlArrayItem, XmlElement and even XmlChoiceIdentifier without any success. I'm thinking something along the lines of the following which won't compile because apparently the XmlArrayAttribute can only be used once per property.
[XmlArray("largeImages")]
[XmlArray("smallImages")]
[XmlArrayItem("largeImage")]
[XmlArrayItem("smallImage")]
public image[] images { get; set; }
Obviously I could merge the 2 arrays in code after the XML is deserialized but it seems like this should be a simple thing to do.
XPATH is probably your answer assuming you don't really care about having it mapped to a class. XPath wildcards on node name gives an example of how you'd select multiple items - http://csharp.net-tutorials.com/xml/using-xpath-with-the-xmldocument-class/ gives an example of how it's used in C#.
Another way muight be using XSLT: Using the code: How to apply an XSLT Stylesheet in C# and XSLT like Combining elements from 2 lists in XSLT should get you what you want.
Personally I'd go with whatever makes life easiest since it doesn't look like you really care in this example what the intermediate data structure is.
Given that the answer from How to define multiple names for XmlElement field? works primarily for elements not arrays, the easiest solution would seem to be to introduce a surrogate property for one of the image elements, say <smallImages>:
public class root
{
[XmlArray("largeImages")]
[XmlArrayItem("largeImage")]
public List<image> Images { get; set; } = new List<image>();
[XmlArray("smallImages")]
[XmlArrayItem("smallImage")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
public List<image> SmallImagesSurrogate { get { return Images; } }
public bool ShouldSerializeSmallImagesSurrogate() { return false; }
}
Notes:
When deserializing to a pre-allocated List<T>, XmlSerializer will simply append deserialized elements to the existing list. That allows elements from both <largeImages> and <smallImages> to be concatenated into the same collection without data loss.
The surrogate property must be public but can be made "less visible" by setting attributes such as [Browsable(false)].
XmlSerializer can successfully deserialize get-only collection properties as long as the collection is pre-allocated. I took advantage of this to avoid adding a setter for the surrogate.
In case you need to re-serialize your root, the method ShouldSerializeSmallImagesSurrogate() will prevent the images array from being double-serialized. (For an explanation of why, see ShouldSerialize*() vs *Specified Conditional Serialization Pattern.) Instead all the images will serialize under <largeImages>. This method does not affect deserialization.
Sample working .Net fiddle.
Simple!!! I do it all the time. The trick is with root that you need to use Elements() and then use FirstOrDefault() to get only one.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Root root = doc.Elements("root").Select(x => new Root() {
Images = x.Descendants("largeImage").Select(z => new Image() {
url = (string)z.Element("url"),
height = (int)z.Element("height"),
width = (int)z.Element("width")
}).ToList()
}).FirstOrDefault();
root.Images.AddRange(doc.Descendants("smallImage").Select(z => new Image() {
url = (string)z.Element("url"),
height = (int)z.Element("height"),
width = (int)z.Element("width")
}).ToList());
}
}
public class Root
{
public List<Image> Images { get; set; }
}
public class Image
{
public string url { get; set; }
public int height { get; set; }
public int width { get; set; }
}
}
I had a challenge with model serialization, and thanks to MSDN I found the answer. Here is my solution:
public class Document
{
[XmlElement(ElementName = "seller_id")]
public string SellerId { get; set; }
[XmlArray(ElementName = "order_details")]
[XmlArrayItem(Type = typeof(SgtinCode), ElementName = "sgtin")]
[XmlArrayItem(Type = typeof(SsccCode), ElementName = "sscc")]
public Code[] Codes { get; set; }
}
public abstract class Code
{
[XmlText]
public string Value { get; set; }
}
public class SgtinCode : Code
{ }
public class SsccCode : Code
{ }
Model setup:
var document = new Document
{
SellerId = Guid.NewGuid().ToString(),
Codes = new Code[]
{
new SsccCode { Value = "111700126101510000000000011" },
new SsccCode { Value ="111700126101510000000000012" },
new SsccCode { Value ="111700126101510000000000013" },
new SgtinCode { Value = "abc" }
}
}
And XML output:
<?xml version="1.0" encoding="utf-8"?>
<documents>
<foreign_shipment>
<seller_id>fb2d35e7-c5d1-43ad-a272-89f897f41058</seller_id>
<order_details>
<sscc>111700126101510000000000011</sscc>
<sscc>111700126101510000000000012</sscc>
<sscc>111700126101510000000000013</sscc>
<sgtin>abc</sgtin>
</order_details>
</foreign_shipment>
</documents>

How to pass dictionary as part of the payload in POST request in Advanced Rest Client

I am trying to use Advanced Rest Client Chrome Extension for testing my WebApi locally
and i would like to pass a dictionary as part of the payload to the POST request that i am trying to make. While debugging i found out that the dictionary even though i am passing it in json format doesn't deserialize correctly and count for Dictionary remains zero.
Payload Example :
{
"DictionaryForEvaluationTelemetries" :{ "B":"{\"Counter\":\"500\"}"}
}
This is the simple code for the object which is part of the dictionary
[DataContract]
class Class1
{
private int counter;
[DataMember]
public int Counter
{
get { return counter; }
}
public void Increment()
{
Interlocked.Increment(ref counter);
}
}
[DataContract]
public class TelemetryPayload
{
[DataMember]
public ConcurrentDictionary<string, Class1> DictionaryForEvaluationTelemetries { get; set; }
}
[HttpPost]
public void LogEvaluationTelemetry()
{
// Internally the below method does : JsonSerializer<T>.Deserialize(request.Content.ReadAsStringAsync().Result);
var telemetryPayload = Request.GetObjectFromBody<TelemetryPayload>();
}
JSON Deserialization is done by System.Runtime.Serialization.Json
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
public static class JsonSerializer<T> where T : class
{
public static T Deserialize(string jsonObject)
{
byte[] array = Encoding.UTF8.GetBytes(jsonObject);
using (MemoryStream ms = new MemoryStream(array))
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(T));
return (T)jsonSerializer.ReadObject(ms);
}
}
As far as I can tell the json you are passing doesn't have an object that will map to Class1. Your json should look like this:
{
"DictionaryForEvaluationTelemetries" : {"B": {"Counter": 500}}
}
where DictionaryForEvaluationTelemetries.B would map to Class1.
Or, depending on what the Request.GetObjectFromBody<> method does, probably more like this:
{"Counter" : 500}
There were two problems for the question asked above :
1) Payload format was incorrect :
{
"DictionaryForEvaluationTelemetries" : {"B": {"Counter": 500}}
}
2) For deserializing i was using System.Runtime.Serialization.Json. I changed it to use NewtonSoft.Json JsonConvert.DeserializeObject

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Facebook;
using Newtonsoft.Json;
namespace facebook
{
class Program
{
static void Main(string[] args)
{
var client = new FacebookClient(acc_ess);
dynamic result = client.Get("fql", new { q = "select target_id,target_type from connection where source_id = me()"});
string jsonstring = JsonConvert.SerializeObject(result);
//jsonstring {"data":[{"target_id":9503123,"target_type":"user"}]}
List<RootObject> datalist = JsonConvert.DeserializeObject<List<RootObject>>(jsonstring);
}
public class Datum
{
public Int64 target_id { get; set; }
public string target_type { get; set; }
}
public class RootObject
{
public List<Datum> data { get; set; }
}
}
}
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type
'System.Collections.Generic.List`1[facebook.Program+RootObject]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly. To fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be
I looked at other posts.
My json looks like this:
{"data":[{"target_id":9503123,"target_type":"user"}]}
To make it clear, in addition to #SLaks' answer, that meant you need to change this line :
List<RootObject> datalist = JsonConvert.DeserializeObject<List<RootObject>>(jsonstring);
to something like this :
RootObject datalist = JsonConvert.DeserializeObject<RootObject>(jsonstring);
As the error message is trying very hard to tell you, you can't deserialize a single object into a collection (List<>).
You want to deserialize into a single RootObject.
Can you try to change your json without data key like below?
[{"target_id":9503123,"target_type":"user"}]
That happened to me too, because I was trying to get an IEnumerable but the response had a single value. Please try to make sure it's a list of data in your response. The lines I used (for api url get) to solve the problem are like these:
HttpResponseMessage response = await client.GetAsync("api/yourUrl");
if (response.IsSuccessStatusCode)
{
IEnumerable<RootObject> rootObjects =
awaitresponse.Content.ReadAsAsync<IEnumerable<RootObject>>();
foreach (var rootObject in rootObjects)
{
Console.WriteLine(
"{0}\t${1}\t{2}",
rootObject.Data1, rootObject.Data2, rootObject.Data3);
}
Console.ReadLine();
}
Hope It helps.
The real problem is that you are using dynamic return type in the FacebookClient Get method. And although you use a method for serializing, the JSON converter cannot deserialize this Object after that.
Use insted of:
dynamic result = client.Get("fql", new { q = "select target_id,target_type from connection where source_id = me()"});
string jsonstring = JsonConvert.SerializeObject(result);
something like that:
string result = client.Get("fql", new { q = "select target_id,target_type from connection where source_id = me()"}).ToString();
Then you can use DeserializeObject method:
var datalist = JsonConvert.DeserializeObject<List<RootObject>>(result);
Hope this helps.
public partial class tree
{
public int id { get; set; }
public string name { get; set; }
public string sciencename { get; set; }
public int familyid { get; set; }
}
private async void PopulateDataGridView()
{
//For Single object response
tree treeobj = new tree();
treeobj = JsonConvert.DeserializeObject<tree>(Response);
//For list of object response
List<tree> treelistobj = new List<tree>();
treelistobj = JsonConvert.DeserializeObject<List<tree>>(Response);
//done
}

Deserializing Google transliteration in C# using Newtonsoft.Json

As a beginner I tried to deserialize Google transliterator return array. It's a JSON array like this:
[{"ew" : "namaste","hws" : ["नमस्ते","नमसते","नमास्ते",]},]
pretty awesome!
This is my c# class used for deserialization:
[Serializable]
public class googleTransliterator
{
[JsonProperty("ew")]
public String sourceWord { get; set; }
[JsonProperty("hws")]
public String[] transliteratedWords { get; set; }
}
and finally:
using Newtonsoft.Json;
...
...
// return value from google transliteration API is in streamReader
var s = new JsonSerializer();
var gt = (googleTransliterator) s.Deserialize( new StringReader( streamReader.ReadToEnd()), typeof( googleTransliterator));
And what I got is:
Cannot create and populate list type GoogleTransliterator.googleTransliterator.
Any idea what is wrong?
The result is an array of JSON objects ([{...},]) instead of a plain object ({...}).
Your code should work if you change it like this:
var gt = ((googleTransliterator[])s.Deserialize(
new StringReader(streamReader.ReadToEnd()),
typeof(googleTransliterator[])))[0];

Categories