Hello I'm trying to serialize an object into a hash, but I'm not getting quite what I want.
Code:
class Data{
public string Name;
public string Value;
}
//...
var l=new List<Data>();
l.Add(new Data(){Name="foo",Value="bar"});
l.Add(new Data(){Name="biz",Value="baz"});
string json=JsonConvert.SerializeObject(l);
when I do this the json result value is
[{"Name":"foo","Value":"bar"},{"Name":"biz","Value":"baz"}]
The result I want however is this:
[{"foo":"bar"},{"biz":"baz"}]
How do I made the JSON come out like that?
Try this for the last line of your method:
string json = JsonConvert.SerializeObject(l.ToDictionary(x=>x.Name, y=>y.Value));
Result: {"foo":"bar", "biz":"baz"}
For result: [{"foo":"bar"},{"biz":"baz"}] you can do this...
string json = JsonConvert.SerializeObject(new object[]{new {foo="bar"}, new {biz = "baz"} });
OR
string json = JsonConvert.SerializeObject(new object[]{new Data1{foo="bar"}, new Data2{biz = "baz"} });
The first result assumes same data type, so results are part of same array. The second is different data types, so you get a different array
you can create your own key value list
like
class mylist:Dictionary<string,object>
{
}
var l=new mylist<Data>();
l.Add("foo","bar");
it should solve your problem
Related
I'm quite new to JSON, and am currently learning about (de)serialization.
I'm retrieving a JSON string from a webpage and trying to deserialize it into an object. Problem is, the root json key is static, but the underlying keys are dynamic and I cannot anticipate them to deserialize. Here is a mini example of the string :
{
"daily": {
"1337990400000": 443447,
"1338076800000": 444693,
"1338163200000": 452282,
"1338249600000": 462189,
"1338336000000": 466626
}
}
For another JSON string in my application, I was using a JavascriptSerializer and anticipating the keys using class structure. What's the best way to go about deserializing this string into an object?
Seriously, no need to go down the dynamic route; use
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
to get a dictionary, and then you can e.g.
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
to get the keys present and the corresponding values.
You can use dynamic in .NET 4 or later. For example with JSON.NET I can do:
dynamic obj = JsonConvert.Deserialize<dynamic>("{x: 'hello'}");
You can then do:
var str = obj.x;
However, unsure how it will handle numeric keys. You can of course just use JObject directly itself, for example:
var obj = JObject.Parse("{'123456': 'help'}");
var str = obj["123456"];
Whenever you have JSON with dynamic keys it can usually be deserialized into a Dictionary<string, SomeObject>. Since the inner JSON keys are dynamic (in this question) the JSON can be modelled as:
Dictionary<string, Dictionary<string, int>>
I would recommend using NewtonSoft.Json (JSON.Net) or System.Text.Json (if you're working in .NET-Core 3.0 and up).
Newtonsoft.Json
Use DeserializeObject<T> from JsonConvert:
var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);
System.Text.Json
Use Deserialize<T> from JsonSerializer:
var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);
This is not convenient to use, because in с# can not be defined a variable starts with a number. Add prefix to keys.
Or try this:
string json = "
{ daily:[
{ key: '1337990400000', val:443447 },
{ key: '1338076800000', val:444693 },
{ key: '1338163200000', val:452282 },
{ key: '1338249600000', val:462189 },
{ key: '1338336000000', val:466626 }]
}";
public class itemClass
{
public string key; // or int
public int val;
}
public class items
{
public itemClass[] daily;
}
items daily = (new JavascriptSerializer()).Deserialize<items>(json);
Then you can:
var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();
I'm trying to update a JSON file with converted list of strings to JSON square brackets "list".
My strings list:
var animals = new List<string>() { "bird", "dog" };
Using this code:
string json = File.ReadAllText(filePath);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var serializedObject = JsonConvert.SerializeObject(animals);
jsonObj["animals"] = serializedObject;
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(filePath, output);
Old JSON file:
{
"animals": ["cat", "fox"]
}
The new JSON file should be:
{
"animals": ["bird", "dog"]
}
But what i get is:
{
"animals": "[\"bird\", \"dog\"]"
}
Any help is appreciated!
Thanks
Your serializedObject is a string, but you don't need it at all it.
As you don't deserialize to a concrete type, your jsonObj["animals"] is just a JArray. So you need this:
dynamic jsonObj = JsonConvert.DeserializeObject(json);
jsonObj["animals"] = JArray.FromObject(animals);
Now you can serialize it back through JsonConvert.SerializeObject.
If that jsonObj was a regular object you could just set the value of the animals property. The same would work if it was an ExpandoObject. JsonConvert.DeserializeObject(json) though generates a Json.Net type whose data must be valid Json.NET types.
You can assing the list contents as a JArray, eg :
var animals = new List<string>() { "bird", "dog" };
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject("{'moo':1}");
jsonObj.animals= new JArray(animals);
var result=JsonConvert.SerializeObject(jsonObj);
The result will be :
{"moo":1,"animals":["bird","dog"]}
Adding a new property will work only if the file contains a JSON dictionary. If you know that the file will alway contain a dictionary, you can cast the deserialization result to JObject, and add the new property through JObject's indexer :
var jsonObj = (JObject)JsonConvert.DeserializeObject("{'moo':1}");
jsonObj["animals"]= new JArray(animals);
My JSON is a very long one and i am fetching only one section "parent_crumbs" from the long JSON
...................,
"parent_crumbs":["Platforms","New platform"],
"promise_by":"2016-08-01",
....
The code I used to fetch value of "parent_crumbs" is
JObject lp_p = JObject.Parse(response_json);
string val= lp_p["parent_crumbs"].ToString();
This returns the following value
"[\r\n \"Platforms\",\"New platform\"\r\n]"
Now I have to do a comparison with the first value from the array as the string is available in a Dictionary as key value and if available return ID
Packages = new Dictionary<string, int>();
Packages.Add("Platforms", 10212);
Packages.Add("New platform", 10202);
Packages.Add("Unknown platform", 10203);
int category=
if(Packages.ContainsKey(val))
{
Packages.TryGetValue(val, out category);
}
So with current code I can't do the comparison straight away due to presence of [\r\n etc.
How to get the value as a string Array without special chars like [\r\n .
Making Model Classes for the JSON for deserialization is not preferred way for me. Since creating class is a big job for me as lot of properties are there in JSON and is dynamic of nature
We can use the below code
var input = "[\r\n \"Platforms\",\"New platform\"\r\n]";
var array =(JArray) JsonConvert.DeserializeObject(input);
bool isEqual = array[0].Value<string>() == "Platforms";
you could also convert it to array with Linq
using System.Linq;
var tmp = lp_p["parent_crumbs"].Select(x => x.ToString());
foreach (var x in tmp)
{
Console.WriteLine(x.ToString());
}
By using Select, it will help you convert it to array rather than to string
You can use DeserializeAnonymousType method for that:
var myType = new
{
parent_crumbs = new []{ "" },
promise_by = default(DateTime)
};
var result = JsonConvert.DeserializeAnonymousType(json, myType);
int category = 0;
string key = result.parent_crumbs[0];
if(Packages.ContainsKey(key))
{
Packages.TryGetValue(key, out category);
}
References: DotNetFiddle Example, DeserializeAnonymousType
I have a string where its a string of a array of dictionaries.
An example of the format is:
[{"id":1,"items":[5,8]},{"id":2,"items":[6]},{"id":3,"items":[7]}]
(Note: all the above code is a string)
So here it is a string of an array of dictionaries that has two keys, the value of the first key is a number, and the value of the second key is a array of numbers.
Using c# (out of the box assemblies), how can I iterate through all the id values, and then all the item array values.
So I would expect like a double for loop. One to iterate through the id's and extract the number, and then for each iteration it would need to iterate through all the values of the items array.
Does anyone know how to go about parsing and extracting the numbers?
Thanks.
The output would be like ( for example )
1
5 8
2
6
3
7
EDIT:
I tried this:
string dataString = JSONValue.Text;
JavaScriptSerializer jss = new JavaScriptSerializer();
var json = new JavaScriptSerializer();
var data = json.Deserialize<List<Dictionary<string, Object>>>(dataString);
int sectionID;
List<int> itemIDS;
foreach (Dictionary<string, Object> dict in data)
{
sectionID = (int)dict["id"];
itemIDS = (List<int>)dict["items"];
ReportObject.log(sectionID.ToString());
foreach (int itemID in itemIDS)
{
ReportObject.log(itemID.ToString());
}
}
But am getting
(6/27/2013 12:02:04 AM) - Error Message: Unable to cast object of type 'System.Collections.ArrayList' to type 'System.Collections.Generic.List`1[System.Int32]'.
try this
using using System.Web.Script.Serialization;
var jsonStr = "[{\"id\":1,\"items\":[5,8]},{\"id\":2,\"items\":[6]},{\"id\":3,\"items\":[7]}]";
var json = new JavaScriptSerializer();
var data = json.Deserialize<List<dynamic>>(jsonStr);
this will generate a list of dynamic object with two properties id and items, then you can loop through that list and retrieve the info which you want.
The dynamic keyword only available from .net 4.0 or later. Otherwise you can use the following option.
create a class like this
public class Info{
public int Id { get; set; }
public int[] Items { get; set; }
}
and then var data = json.Deserialize<List<Info>>(jsonStr);
try getting the int value of string, if it's an array, get the object on the index specifically and try to the ToInt() or cast the string object to int. it can be done both ways.
I want to serialize dynamic object to JSON. I tried using ExpandoObject, but the result is not what I need:
public JsonResult Edit()
{
dynamic o = new ExpandoObject();
((IDictionary<string,Object>)o)["abc"] = "ABC"; //or o.abc = "ABC";
return Json(o);
}
I want JSON to look like: {"abc": "ABC"} but instead it looks like [{"Key":"abc","Value":"ABC"}]
Obviously ExpandoObject will not do, but can I inherit from DynamicObject and somehow override its methods to achieve JSON format I want?
I had this same problem and ended up fixing it by using the JSON.net (Newtonsoft.Json) serializer instead of using the JsonContent result. It then serialized my dynamic objects with normal properties versus the "key" "value" weird list.
//In my usage I had a list of dynamic objects
var output = new List<dynamic>();
//Change this
return JsonContent(new {Error = errorMessage, Results = output});
//to this
return Content(JsonConvert.SerializeObject(new {Error = errorMessage, Results = output}));
This will return what you want.
public JsonResult Edit()
{
return Json(new {abc = "ABC"});
}
This may not be useful to you, but I had a similar requirement, but used a SerializableDynamicObject
I changed the name of the dictionary to "Fields" and then this serializes with Json.Net to produce json which looks like:
{"Fields":{"Property1":"Value1", "Property2":"Value2" etc.
where Property1 and Property2 are Dynamically added properties - i.e. Dictionary Keys
It would be perfect if I could get rid of the extra "Fields" property which encapsulates the rest, but I've worked around that limitation.
You can always serialize a HashTable, its not dynamic but it supports object key value pairs.
This worked for me perfectly. You have to use Json.NET.
[HttpGet]
public string GetJson()
{
List<Dictionary<string, string>> list = new List<Dictionary<string, string>>();
List<DataEntry> properties = new List<DataEntry>();
for (int i = 0; i < 10; i++)
{
properties.Add(new DataEntry { Column = "column" + i.ToString(), Value = "value" + i.ToString() });
}
list.Add(properties.ToDictionary(x => x.Column, y => y.Value));
string test = JsonConvert.SerializeObject(list);
return test;
}