I want to convert a json string to NameValueCollection. I came up with the code below.
public static NameValueCollection ConvertFromJson(string json)
{
var anonymous = JContainer.Parse(json);
var nvc = new NameValueCollection();
var dict = new RouteValueDictionary(anonymous);
foreach (var kvp in dict)
{
if (kvp.Value == null)
{
// I am OK if a property is null. Just skip it.
continue;
}
if (kvp.Value.GetType().Name.Contains("Anonymous"))
{
var prefix = kvp.Key + ".";
foreach (var innerkvp in new RouteValueDictionary(kvp.Value))
{
nvc.Add(prefix + innerkvp.Key, innerkvp.Value.ToString());
}
}
else
{
nvc.Add(kvp.Key, kvp.Value.ToString());
}
}
return nvc;
}
It works well with normal classes but not nested classes. For example, it works with class A but not class B.
class A
{
public string AAA { get; set; }
public int BBB { get; set; }
}
class B
{
public string AAA { get; set; }
public MyOtherClass BBB { get; set; }
}
How can I convert nested objects to NameValueCollection?
Explain
This question is absolutely not duplicate with How to convert json to NameValueCollection. The answer in that question only works with class A but it does not work with class B.
If you only whant to serialise/deserialise a nested object like you shared on the question you could use a work around like this:
Dictionary <string, object> deserializedresult = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
The only problem with it that you need to serialise and desrialise again the nested objects or use reflection to reach the contained elements of the nested objects.
Related
Requirement
I am trying to build a function that takes a json string as input. and outputs list of object.
The json string is in a similar format to this:
{\"custlist\":[{\"cust_name\":\"Vincent\",\"cust_id\":\"klq:206f387:2d08m92t6\"},{\"cust_name\":\"Joyce\",\"cust_id\":\"125g:1474grx:2d03t9dld\"}]}
My Search
There are plenty of solutions deserialize json array to list of objects, but the array starts at the beginning of the string. i.e. without the \"custlist\": part
If we have \"custlist\": part in the json string, those solutions break.
My Code
Here is my code in C#. It is working, but I had to use regular expression to match the input string. Seems over-complicated. There must be an easier way. Anyone knows, please kindly advise
public void Test()
{
string str = {\"custlist\":[{\"cust_name\":\"Vincent\",\"cust_id\":\"klq:206f387:2d08m92t6\"},{\"cust_name\":\"Joyce\",\"cust_id\":\"125g:1474grx:2d03t9dld\"}]};
List<Customer> list = Json2List<Customer>(str);
foreach (Customer c in list)
{
console.writeline ("name=" + c.cust_name);
console.writeline ("id=" + c.cust_id);
}
}
public List<T> Json2List<T>(string s)
{
string json_listname = Regex.Match(s, "\"" + #"(\w+?)" + "\":").Groups[0].Value;
JObject jObject = JObject.Parse(s);
List<JToken> jTokenList = jObject.GetValue(json_listname).ToList();
List<T> LstT = new List<T>();
foreach (JToken jt in jTokenList)
{
T obj = jt.ToObject<T>();
LstT.Add(obj);
}
return LstT;
}
public class Customer
{
public string cust_name { get; set; }
public string cust_id { get; set; }
}
I am really lost as to what the problem is, but essentially:
public class CustomerList {
[JsonProperty("custlist")]
public Customer[] Customers { get; set; }
}
public class Customer
{
[JsonProperty("cust_name")]
public string Name { get; set; }
[JsonProperty("cust_id")]
public string Id { get; set; }
}
var sample = "{\"custlist\":[{\"cust_name\":\"Vincent\"},{\"cust_id\":\"klq206f3872d08m92t6\"},{\"cust_name\":\"Joyce\"},{\"cust_id\":\"125g1474grx2d03t9dld\"}]}";
var result = JsonConvert.DeserializeObject<CustomerList>(sample).Customers;
// Or!
var dictResult = JsonConvert.DeserializeObject<Dictionary<string, Customer[]>>(sample)["custlist"];
Looks like it's a JSON object that is stored in a JSON string.
So deserialize it as a string first, then as a list of the correct type. You can do both using JsonConvert.DeserializeObject:
Update: I just realized that the array in the JSON is a property of the JSON object, which I didn't account for here. I don't have time to fix that right now, but I hope you get the idea.
public List<T> Json2List<T>(string s)
{
string json_object = JsonConvert.DeserializeObject<string>(s);
return JsonConvert.DeserializeObject<List<T>>(json_object);
}
But I would also look into why the data you're getting is double-serialized like that.
I'm trying to make use of Netwonsoft.JSON.Linq in C#, to change the "statusCode" values in the following JSON:
{
"disbursements":[
{
"id":"1f337641",
"contactId":"f5eb2",
"statusCode":166000005,
"amount":8,
"category":166000001
},
{
"id":"027a4762",
"contactId":"f5eb2038",
"statusCode":166000000,
"amount":4000,
"category":166000000
}
]
}
So, inside the JSON data is: "disbursements" which is JSON array. I have to change the "statusCode" of each item in the array to 166000005. I'm able to retrieve statusCode of the first one using
JObject jsonText = JObject.Parse(bodyText);
var statusCode = (int)jsonText.SelectToken("disbursements[0].statusCode");
But I need a solution with loop or LINQ that changes all the values, not just the first.
The following code sets or adds "statusCode": 166000005 to every entry in the disbursement array:
var jsonText = JObject.Parse(bodyText);
foreach (var disbursement in jsonText.SelectTokens("disbursements[*]"))
{
disbursement["statusCode"] = 166000005;
}
Notes:
The query string "disbursements[*]" contains the JSONPath wildcard operator [*]. This operator matches all array elements under the parent element "disbursement".
Json.NET supports JSONPath syntax as documented in Querying JSON with JSONPath.
SelectTokens() is used rather than SelectToken() to loop through multiple possible matches.
The JToken item setter disbursement["statusCode"] = 166000005 will replace the "statusCode" property if present and add it if not.
A simple, atomic value such as 166000005 can be set directly into a JToken hierarchy. For a complex POCO you would need to call JToken.FromObject() to serialize it to a JToken before setting it in the hierarchy, e.g.:
disbursement["statusCode"] =
JToken.FromObject( new { oldValue = disbursement["statusCode"], newValue = 166000005 } );
Sample working .Net fiddle.
I would create classes to represent the data. Here is my solution:
Create the data holder classes:
public class Disbursement
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("contactId")]
public string ContactId { get; set; }
[JsonProperty("statusCode")]
public int StatusCode { get; set; }
[JsonProperty("amount")]
public int Amount { get; set; }
[JsonProperty("category")]
public int Category { get; set; }
}
The collection:
public class Disbursements
{
[JsonProperty("disbursements")]
public List<Disbursement> Items { get; set; } = new List<Disbursement>();
}
And then the loading / modifying / saving data:
class Program
{
static void Main(string[] args)
{
var disbursements =
JsonConvert.DeserializeObject<Disbursements>(
File.ReadAllText(
"data.json",
Encoding.UTF8
)
);
foreach (var disbursement in disbursements.Items)
{
disbursement.StatusCode = 166000005;
}
string modifiedContent = JsonConvert.SerializeObject(disbursements);
File.WriteAllText(
"modifiedData.json",
modifiedContent,
Encoding.UTF8
);
}
}
This is the code I use to deserialize JSON.But when I try writing it in console, it says "System.Collections.Generic.Dictionary`2[System.String, System.Object]"
System.Net.WebClient wc = new System.Net.WebClient();
string Jayson = wc.DownloadString("http://api.urbandictionary.com/v0/define?term=api");
object obj = JsonHelper.Deserialize(Jayson);
Dictionary<string, object> values =
JsonConvert.DeserializeObject<Dictionary<string, object>>(Jayson);
Console.WriteLine(values);
How do I deserialize it and extract only the "definition" from the JSON?
You can create some concrete types to map to and deserialize using those rather than more generic types, for example:
public class Result
{
[JsonProperty("definition")]
public string Definition { get; set; }
[JsonProperty("author")]
public string Author { get; set; }
[JsonProperty("permalink")]
public string PermaLink { get; set; }
}
public class Results
{
[JsonProperty("list")]
public List<Result> List { get; set; }
[JsonProperty("tags")]
public List<string> Tags { get; set; }
}
Then:
var results = JsonConvert.DeserializeObject<Results>(json);
You can then iterate the definitions:
foreach(var result in results.List)
Console.WriteLine(result.Definition);
Json.NET will ignore the other properties it can't map so you can add/remove them as needed.
You're getting "System.Collections.Generic.Dictionary`2[System.String, System.Object]" because Console.WriteLine can only write strings and it doesn't know how to turn a dictionary into a string.
To print all the entries, loop over the collection and print each entry:
System.Net.WebClient wc = new System.Net.WebClient();
string Jayson = wc.DownloadString("http://api.urbandictionary.com/v0/define?term=api");
object obj = JsonHelper.Deserialize(Jayson);
Dictionary<string, object> values =
JsonConvert.DeserializeObject<Dictionary<string, object>>(Jayson);
foreach(var entry in values)
{
Console.WriteLine($"{entry.Key} : {entry.Value}");
}
Just parse your json string to a JObject and then get the "defenition" property from it
jObj = JObject.Parse("yourJsonString");
string defenition = jo["definition"];
What is the best way to map a JSON object that has a structure whereby it contains a list of objects whose names are dynamically created through incrementation?
e.g.
{"data":
{
"object-0":[{"id":"1","name":"John"},{"id":"2","name":"Mary"}],
"object-1":[{"id":"3","name":"Gary"},{"id":"4","name":"Mark"}]
}
}
Assuming you've got a class like
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
You could deserialize this into a Dictionary<string, IEnumerable<User>> like so
Dictionary<string, IEnumerable<User>> values =
JsonConvert.DeserializeObject<Dictionary<string, IEnumerable<User>>>(json);
This also assumes the use of json.net
You can use Json.NET library to transform any JSON string to arbitrary dynamic object in .NET. This should do:
dynamic jsonObject = JsonConvert.DeserializeObject(jsonString);
In your case I suppose you need object-0, object-1 etc in a list/array (since they are incrementally generated by the looks of it) and not as typed properties as such, in which case you can trivially transform the obtained dynamic object to whatever you want. For an e.g.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Data
{
public Dictionary<string, List<User>> Objects { get; set; }
}
string jsonString = '...';
dynamic jsonObject = JsonConvert.DeserializeObject(jsonString);
// could have made use of LINQ to shorten this bit of code
// but unfortunately dynamic doesn't play well with extension methods
var data = new Data { Objects = new Dictionary<string, List<User>>() };
foreach (var obj in jsonObject.data)
data.Objects[obj.Name] = obj.Value.ToObject<List<User>>();
// now you have everything in `data` instance.
To replicate the exact json structure, you can have a root class to hold the data. Something like:
class Root { public Data data { get; set; } }
var root = new Root { data = data };
If you need the entire user objects in one flat structure, you can flatten it too:
var users = data.Objects.SelectMany(kv => kv.Value);
I have a dictionary of strings and object that i obtained deserializing this json answer:
{"labels":[{"id":"1","descrizione":"Etichetta interna","tipo":"0","template_file":"et_int.txt"},{"id":"2","descrizione":"Etichetta esterna","tipo":"1","template_file":"et_ext.txt"}],"0":200,"error":false,"status":200}
using the code:
var labels = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Now i want to loop only trought the objects inside the "labels" key.
I tried
foreach (var outer in labels["labels"]){/* code */}
but i got error:
CS1579: foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public definition for 'GetEnumerator'.
Solved replacing the dictionary with a class, thank you
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).
[TestMethod]
public void test()
{
string json = "{\"labels\" : [{\"id\" : \"1\",\"descrizione\" : \"Etichetta interna\",\"tipo\" : \"0\",\"template_file\" : \"et_int.txt\"}, {\"id\" : \"2\",\"descrizione\" : \"Etichetta esterna\",\"tipo\" : \"1\",\"template_file\" : \"et_ext.txt\"}],\"0\" : 200,\"error\" : false,\"status\" : 200}";
var root = JsonConvert.DeserializeObject<Rootobject>(json);
foreach (var label in root.Labels)
{
//Use label.Id, label.Descrizione, label.Tipo, label.TemplateFile
}
}
public class Rootobject
{
public Label[] Labels { get; set; }
public int _0 { get; set; }
public bool Error { get; set; }
public int Status { get; set; }
}
public class Label
{
public string Id { get; set; }
public string Descrizione { get; set; }
public string Tipo { get; set; }
public string TemplateFile { get; set; }
}
You need to loop through your dictionary.
foreach(KeyValuePair<string, Object> entry in labels)
{
// do something with entry.Value or entry.Key
}
Once you start looping through it you will get access to key and value. Since you are interested to look at entry.value you can do operation on that easily. Currently your dictionary value is type of object which does not have an enumerator
Your problem is that you've defined the Type of Value for each dictionary entry as object. C# can't know how to loop over on object. So you need to work out what type is actually inside the object once the JavaScriptSerializer have parsed the JSON. One way is
var t = typeof(labels["labels"]);
Once you know what type the serializer is creating, all you need to do is cast the object back to that type. For example, assuming it's a list of objects
var labels = (List<object>)labels["labels"];
foreach (var label in labels)
{
}
Alternatively, if each object in the JSON is the same, you could try create the dictionary as the type you need. So you serializing becomes
var labels = new JavaScriptSerializer()
.Deserialize<Dictionary<string, List<object>>>(json);
A possible solution:
static void Main(string[] args) {
string json = #"{'labels':[{'id':'1','descrizione':'Etichetta interna','tipo':'0','template_file':'et_int.txt'},{'id':'2','descrizione':'Etichetta esterna','tipo':'1','template_file':'et_ext.txt'}],'0':200,'error':false,'status':200}";
var labels = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
IEnumerable inner_labels = labels["labels"] as IEnumerable;
if (inner_labels != null) {
foreach (var outer in inner_labels) {
Console.WriteLine(outer);
}
}
}
Otherwise, you can create a class with deserialization information and instruct the deserializer to deserialize your json string to that type:
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
[Serializable]
public class JsonData {
[XmlElement("labels")]
public List<JsonLabel> labels { get; set; }
[XmlElement("0")]
public int zero { get; set; }
[XmlElement("error")]
public bool error { get; set; }
[XmlElement("status")]
public int status { get; set; }
}
[Serializable]
public class JsonLabel {
[XmlElement("id")]
public int id { get; set; }
[XmlElement("descrizione")]
public string descrizione { get; set; }
[XmlElement("tipo")]
public int tipo { get; set; }
[XmlElement("template_file")]
public string template_file { get; set; }
}
class Program {
static void Main(string[] args) {
string json = #"your json string here...";
var jsonData = new JavaScriptSerializer().Deserialize<JsonData>(json);
foreach (var label in jsonData.labels) {
Console.WriteLine(label.id);
}
}
}
Could you please try below snippet?
It might be help you.
foreach (var item in labels["labels"] as ArrayList)
{
Console.Write(item);
}