How to avoid a property name during serialization? Below an example
public class A {
public List<object> Values { get; set; }
public string Name { get; set; }
}
A a = new A();
a.Name = "Numbers"
a.Values = new List<object>();
a.Values.Add(1);
a.Values.Add(2);
a.Values.Add(3);
a.Values.Add(4);
JsonConvert.SerializeObject(new { a });
After serialization, result includes a property names "values"
{
"a": {
"values": [
1,
2,
3,
4
],
"name": "Numbers"
}
}
but, I need the following
{
"a": [
1,
2,
3,
4
],
"name": "Numbers"
}
Just serialize a.Values;
JsonConvert.SerializeObject(a.Values);
You have a couple mistakes in your code.
First, if you want this class:
public class A
{
public List<object> Values { get; set; }
public string Name { get; set; }
}
To serialize to this json:
{
"a": [
1,
2,
3,
4
],
"name": "Numbers"
}
You are gonna have a bad time. Just look at the structure, they are not 1-1.
You need to change your class, make sure you name it something meaningful (a class of a single letter is a really bad idea).
public class SomeClass
{
[JsonProperty("a")]
public List<object> Values { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
You notice the [JsonProperty()] attribute above? That tells the serializer that this property should serialize with the defined name. That way you can have a meaningful property name ("Values") while in code, and still have the json serialize the way you want it to ("a").
The second problem is when you serialize you are creating a new anonymous object with a property of the class you instance you created. Which will again mess your structure up. Change your serialization code to just serialize the object instance:
string json = JsonConvert.SerializeObject(someInstanceOfYourClass);
My above changes should give you json that looks like this:
{
"a": [
1,
2,
3,
4
],
"name": "Numbers"
}
I have made a fiddle here that will demonstrate.
Related
I am supposed to read the following JSON response:
ValueFilters:[
{field:"amount", comparitor:"GREATER", "value": 0},
{operator:"AND"},
{field:"id", comparitor:"LESS", "value": 5}]
If it did not contain 'operator' object then I would not have any problem, but with it how do I construct the equivalent C# object?
First off, your example, the JSON is not valid JSON. To make it valid, one must add quotes to each of the property names such as field to "field". Once that is done the Json can be parsed:
{
"ValueFilters": [
{
"field": "amount",
"comparitor": "GREATER",
"value": 0
},
{
"operator": "AND"
},
{
"field": "id",
"comparitor": "LESS",
"value": 5
}
]
}
By taking that valid Json above it can be serialized into these C# classes:
public class Filters
{
public List<ValueFilter> ValueFilters { get; set; }
}
public class ValueFilter
{
[JsonPropertyName("operator")] // Handle the C# `operator` keyword.
public string Operator { get; set; }
public string field { get; set; }
public string comparitor { get; set; } // Misspell -> comparator
public int value { get; set; }
}
Using your favorite derializer would look like this, .Net 5 System.Text.Json shown:
var filter = JsonSerializer.Deserialize<Filters>(data);
Which when deserialized you have 3 ValueFilter items. By checking whether the Operator property is not null or not, the future code knows what to do with the data.
Operator
field
comparitor
value
null
amount
GREATER
0
AND
null
null
0
null
id
LESS
5
...and "beautiful" is sarcastic here.
When you call Active Campaign's list_view endpoint, and would like to get that in a json response, then this is the json response you get:
{
"0": {
"id": "4",
"name": "Nieuwsletter 1",
"cdate": "2018-11-22 03:44:19",
"private": "0",
"userid": "6",
"subscriber_count": 2901
},
"1": {
"id": "5",
"name": "Newsletter 2",
"cdate": "2018-11-22 05:02:41",
"private": "0",
"userid": "6",
"subscriber_count": 2229
},
"2": {
"id": "6",
"name": "Newsletter 3",
"cdate": "2018-11-22 05:02:48",
"private": "0",
"userid": "6",
"subscriber_count": 638
},
"result_code": 1,
"result_message": "Success: Something is returned",
"result_output": "json"
}
Now how would I ever be able to deserialize this to an object? Doing the normal Edit => Paste Special => Paste JSON As Classes gives me an output where I end up with classes that named _2.
Also, JsonConvert throws the following error: Accessed JObject values with invalid key value: 2. Object property name expected. So it is not really able to deserialize it either. I tried to use dynamic as object type to convert to.
The only thing I can think of now is replacing the first { by [ and the last } by ], then remove all the "1" : items and then remove the last 3 properties. After that I have a basic array which is easy convertable. But I kind of hope someone has a better solution instead of diving deep into the string.indexOf and string.Replace party...
If your key/value pair is not fixed and data must be configurable then Newtonsoft.json has one feature that to be used here and that is [JsonExtensionData]. Read more
Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.
In your case key/value pair with 0,1,2,3.......N have dynamic data so your class will be
So create one property that collects all of your dynamic key/value pair with the attribute [JsonExtensionData]. And below I create that one with name DynamicData.
class MainObj
{
[JsonExtensionData]
public Dictionary<string, JToken> DynamicData { get; set; }
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
}
And then you can deserialize your JSON like
string json = "Your json here"
MainObj mainObj = JsonConvert.DeserializeObject<MainObj>(json);
Edit:
If you want to collect your dynamic key's value to class then you can use below the class structure.
class MainObj
{
[JsonExtensionData]
public Dictionary<string, JToken> DynamicData { get; set; }
[JsonIgnore]
public Dictionary<string, ChildObj> ParsedData
{
get
{
return DynamicData.ToDictionary(x => x.Key, y => y.Value.ToObject<ChildObj>());
}
}
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
}
public class ChildObj
{
public string id { get; set; }
public string name { get; set; }
public string cdate { get; set; }
public string _private { get; set; }
public string userid { get; set; }
public int subscriber_count { get; set; }
}
And then you can deserialize your JSON like
MainObj mainObj = JsonConvert.DeserializeObject<MainObj>(json);
And then you can access each of your deserialized data like
int result_code = mainObj.result_code;
string result_message = mainObj.result_message;
string result_output = mainObj.result_output;
foreach (var item in mainObj.ParsedData)
{
string key = item.Key;
ChildObj childObj = item.Value;
string id = childObj.id;
string name = childObj.name;
string cdate = childObj.cdate;
string _private = childObj._private;
string userid = childObj.userid;
int subscriber_count = childObj.subscriber_count;
}
I'd recommend JObject from the Newtonsoft.Json library
e.g. using C# interactive
// Assuming you've installed v10.0.1 of Newtonsoft.Json using a recent version of nuget
#r "c:\Users\MyAccount\.nuget\.nuget\packages\Newtonsoft.Json\10.0.1\lib\net45\Newtonsoft.Json.dll"
using Newtonsoft.Json.Linq;
var jobj = JObject.Parse(File.ReadAllText(#"c:\code\sample.json"));
foreach (var item in jobj)
{
if (int.TryParse(item.Key, out int value))
{
Console.WriteLine((string)item.Value["id"]);
// You could then convert the object to a strongly typed version
var listItem = item.Value.ToObject<YourObject>();
}
}
Which outputs:
4
5
6
See this page for more detail
https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm
I have an web API function that has a property that can take different shapes. Actually i need to save a json in database.
I will give you some examples
post body
{
"title":"example 1",
"type": "0",
"extraData": { "name": "bob",
// here is the catch this is first type of object let's say children
[{
"age": 10
"toys": "bear, goat"
},
{
"age": 18
"toys": "guitar"
}]
}
}
{
"title":"example 1",
"type": "1",
"extraData": { "name": "john",
// here is the catch this is first type of object let's say grandparents
[{
"age": 90
"cars": "honda civic"
},
{
"age": 18
"car": "renault megan, pegeout 206"
}]
}
}
Now let's assume that we can't merge grandparents and children together in a class so my classes will look something like:
public class Family{
public string Title {get; set;}
public string ExtraData {get; set;}
public int Type {get;set;}
}
public class ExtraData<T> where T: Person{
public string Name{get;set;}
public List<T> Persons {get;set;}
}
public class Person{
public int Age {get;set;}
}
public class Child : Person{
public string Toys{get;set;}
}
public class Grandparent : Person{
public string Cars{get;set;}
}
In the api method I was thinking to do something like:
public void Save(Family model)
{
// to parse extraData my idea was to
switch(mode.Type)
{
case 0: var childrens = JsonConvert.DeserializeObject<ExtraData<Child>>(model.ExtraData);
// do stuff
break;
case 1: var grandparents = JsonConvert.DeserializeObject<ExtraData<Child>>(model.ExtraData);
// do stuff
break;
}
// save the object
}
The issue is that on the api call I get nothing in the extraData string. And I can't put in Family something like
public ExtraData<Person> Persons {get;set;}
because it will deserialize to the base type and I will lose the subclass information.
I know is to do something like json stringify but I would like this to be my last resort. Also i have tried to use dynamic instead of Family but I still need to deserialze it and having same issue.
What is the best approach here?
I'm having problems when trying to save an object that has a dynamic property in RavenDB
The object I'm trying to save represents an order. The order contains a list of orderlines so imagine the following Order class:
public class Order {
public int Id { get; set; }
public List<Orderline> Orderlines { get; set; }
}
And the Orderline class being:
public class Orderline {
public Product Product { get; set; }
public int Quantity { get; set; }
public dynamic Attributes { get; set; }
}
The object I'm trying to save (I'll display it with JSON);
{
"Id": 0,
"Orderlines": [
{
"Product": {
"Id": 0,
"Name": "Some product"
},
"Quantity": 1,
"Attributes": {
"color": "Red"
}
}
]
}
Saving it does not throw any errors
RavenDB stores the Order object as
{
"Id": 0,
"Orderlines": [
{
"Product": {
"Id": 0,
"Name": "Some product"
},
"Quantity": 1,
"Attributes": {
"$type": "Newtonsoft.Json.Linq.JObject, Newtonsoft.Json",
"color": {
"$type": "Newtonsoft.Json.Linq.JValue, Newtonsoft.Json",
"$values": []
}
}
}
]
}
Note that the values property of Order.Orderlines[0].Attributes.color is not set...
When I try to serialize the object back to my C# Order object I get the following exception;
Unable to cast object of type
'Raven.Imports.Newtonsoft.Json.Utilities.CollectionWrapper`1[Newtonsoft.Json.Linq.JToken]'
to type 'Newtonsoft.Json.Linq.JValue'.
What am I doing wrong, how can I store this object in the RavenDB database and retrieve it?
What is the type that you are actually saving into attributes?
Typically you'll use something that is actually dynamic, like ExpandoObject
Storing the dynamic property with type 'dynamic' apparently wasn't enough. When I gave the Attributes property the ExpandoObject type, RavenDB stored the Attributes property as normal JSON (without $type and $values, so clean as desired)
When retrieving it back from the RavenDB database it deserializes back to an ExpandoObject object.
Make sure to cast the ExpandoObject property to a dynamic (e.g. 'as dynamic') when trying to display the property in a Razor view.
In one of my project i want to parse a JSON array with different key name. For Example
{ "details": [
{ "state": "myState1",
"place": [
{ "name": "placeName" } ] },
{ "state": "myState2",
"place": [
{ "name1": "placeName" } ] },
{ "state": "myState3",
"place": [
{ "name2": "placeName" } ] } }
So in this JSON please look at the place array. each time key like name1,name2,name3...,
.And also it is not necessary to get the same JSON at all the time. In some time only state1 or state1 and state3 and in some time state1 to state 50.
So how can i identify and parse exact data from this array
First of all your JSON is not well-formatted. You miss a closing square bracket ] before the last closing curly bracket }.
Then, you can't parse variable-name properties to a static class, but you can turn them into a dictionary. Here's an example of mapping classes that work with variable places:
public class Details
{
public string state { get; set; }
public List<Dictionary<string, string>> place { get; set; }
}
public class Wrap
{
public Details[] details { get; set; }
}
static void Main(string[] args)
{
string txt = File.ReadAllText("MyJSONFile.txt");
JavaScriptSerializer ser = new JavaScriptSerializer();
var data = ser.Deserialize<Wrap>(txt);
}
If also the place property will change name, I think the simplest way to parse it is to use the following, very loosely typed, class:
public class Wrap
{
public List<Dictionary<string,object>> details { get; set; }
}
where the object in the dictionary will be a string or a dictionary of properties according to the values in the JSON.