Unusual JSON construct - c#

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

Related

Create key:value Json based on a list of objects

I'm receiving from an API a result that is something like:
[{
"propID": 1,
"propname": "nameA",
"dataType": "N",
"value": "9"
},
{
"propID": 2,
"propname": "nameB",
"dataType": "VL",
"value": "dasdsa"
},
{
"propID": 3,
"propname": "nameC",
"dataType": "N",
"value": "7"
},
{
"propID": 4,
"propname": "nameD",
"dataType": "VL",
"value": "jmfidsnjfs"
}
]
I'm getting this and decoding this into an DTO so I can convert the numeric values into numerics.
My DTO looks like:
public class PropertyToInsertDto
{
[JsonIgnore]
public int propID { get; set; }
public string propname { get; set; }
[JsonIgnore]
public string dataType { get; set; }
[JsonIgnore]
public string value { get; set; }
public string valueString { get; set; }
public float valueInt { get; set; }
}
So, imagining I store the API into string variable called result I would decode this using
var properties = JsonConvert.DeserializeObject<List<PropertyToInsertDto>>(result);
and then iterating each property to convert into numeric values
foreach(var property in properties) {
if (string.IsNullOrEmpty(property.value))
continue;
if (property.dataType == "N") {
property.valueInt = float.Parse(property.value);
} else {
property.valueString = property.value;
}
}
I want to convert this into Json so the result is
{"nameA": 9, "nameB":"dasdsa", "nameC":7, "nameD": "jmfidsnjfs"}
I tried using the SerializeObject method from JsonConvert without any good result.
My biggest problem is due to the fact that the result can come from valueInt or valueString depending if it is a number or a text.
Thanks!
Kuno
First of all you ignored "value" property, so this property isn't deserialized by JsonConvert and always has default value.
[JsonIgnore]
public string value { get; set; }
"valueString" and "valueInt" aren't required in this DTO, you need separated DTOs to read and write because you are changing object structure.
You can get expected result using this code:
var properties = JsonConvert.DeserializeObject<List<PropertyToInsertDto>>(str);
var result = JsonConvert.SerializeObject(properties.ToDictionary(
x => x.propname,
x => x.dataType == "N" ? (object)float.Parse(x.value) : x.value));
You can create a dictionary and then convert it to a json like this:
https://www.newtonsoft.com/json/help/html/SerializeDictionary.htm
Instead of int type as the value you can use object. Or use a string even for number types, but you would have to use custom convert type when deserializing in the future operations.
This might help as well:
Serializing/Deserializing Dictionary of objects with JSON.NET

Avoid serialization of a property name in json.net

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.

Json DeserializeObject into class with dynamic property

I'm trying to convert a string of JSON data into a C# class object. However I'm having an issue with a small part of the JSON which is dynamic in nature.
The part of the JSON is below:
"contact": [{
"comment": null,
"type": {
"id": "cell",
"name": "Example name"
},
"preferred": true,
"value": {
"country": "7",
"formatted": "+7 (702) 344-3423-3",
"number": "3498908",
"city": "702"
}
},
{
"type": {
"id": "email",
"name": "Email example"
},
"preferred": false,
"value": "name#mail.com"
}]
C# classes
public class Value
{
public string country { get; set; }
public string formatted { get; set; }
public string number { get; set; }
public string city { get; set; }
}
public class Type
{
public string id { get; set; }
public string name { get; set; }
}
public class Contact
{
public string comment { get; set; }
public Type type { get; set; }
public bool preferred { get; set; }
public string value { get; set; }
}
C# Code
Contact contact = JsonConvert.DeserializeObject<Contact>(result);
The format of "value" changes depending on the contact information. Is it possible to map value both as a string and also class Value.
Thanks for any help that can be provided.
You can literally just use dynamic, i.e.
public dynamic value { get; set; }
If it looks like an object, it will be materialized as a JObject, which can be used via the dynamic API, so .value.country will work, etc. If it looks like an integer, bool or string: it will be materialized as such. Arrays will also be handled suitably. So: you can check whether .value is string, etc. Note that this won't use your Value type, and doing so is more complex, but: meh; you get the data. You can always switch that out manually.
It will also behave like this if you use object instead of dynamic, but then it is harder to access the inner properties.
Try
Contact contact = JsonConvert.DeserializeObject<Contact>(result[0]);
As you can see in the JSON, it's
"contact": [
Indicating an array, currently you're just passing the entire array
Unless you're sure that the JSON comes always with the same structure, the best is to use a dynamic variable instead of deserialize it into a class.
If you like to work with classes you can always build your own on runtime using reflection. But that's like killing a fly with a cannon and you're probably won't need it, so just use a dynamic variable instead, it's the best to work with JSON strings.

How to mapping a multiple type javascript array to C# array

I use asp.net MVC model binding to accept the parameters for ajax.
I have an object, it's data structure like this:
{
"conditions": [
{
"field": "",
"opreator": "",
"value": ""
},[{
"field": "",
"opreator": "",
"value": ""
},
{
"field": "",
"opreator": "",
"value": ""
}]
],
"name": "query",
}
C# array can't has different types. (the property conditions is an arrray that has object and array).
So I defined an object array.
public class QueryVM
{
public class condition
{
public string field { get; set; }
public string opreator { get; set; }
public string value { get; set; }
}
public object[] conditions { get; set; }
public string name { get; set; }
}
But what I received the property conditions is just an object array. I can't access it's actual property, I even don't know it's actual type is(QueryVM.condition or array). I thinks the model binding even not set value of the properties. So this is a bad way.
I want know whether there is other way to do this?
UPDATE
The conditions property of QueryVM is an object array because it's contain object and array.
Conditions should be an array of type condition instead of simple object.
Try replacing
public object[] conditions { get; set; }
with
public condition[] conditions { get; set; }
actually you are sending list of type object because the type is not defined so you can do something like this
public List<object> conditions { get; set; }
this will get the list but your json should be like this
conditions:[{
"field": "",
"opreator": "",
"value": ""
},
{
"field": "",
"opreator": "",
"value": ""
}]
and your then your type will be
public List<condition> conditions { get; set; }

Model to match this JSON for deserialization, field names with dashes

I am trying to create a model that would match the JSON.NET deserealization of this JSON structure:
First item...
{
"190374": {
"vid": 190374,
"canonical-vid": 190374,
"portal-id": 62515,
"is-contact": true,
"profile-token": "AO_T-mN1n0Mbol1q9X9UeCtRwUE1G2GFUt0VVxCzpxUF1LJ8L3i75x9NmhIiS0K9UQkx19bShhlUwlIujY4pSXAFPEfDG-k9n8BkbftPw6Y5oM3eU5Dc_Mm-5YNJTXiWyeVSQJAN_-Xo",
"profile-url": "https://app.hubspot.com/contacts/62515/lists/public/contact/_AO_T-mN1n0Mbol1q9X9UeCtRwUE1G2GFUt0VVxCzpxUF1LJ8L3i75x9NmhIiS0K9UQkx19bShhlUwlIujY4pSXAFPEfDG-k9n8BkbftPw6Y5oM3eU5Dc_Mm-5YNJTXiWyeVSQJAN_-Xo/",
"properties": {
"phone": {
"value": "null"
},
"hs_social_linkedin_clicks": {
"value": "0"
},
"hs_social_num_broadcast_clicks": {
"value": "0"
},
"hs_social_facebook_clicks": {
"value": "0"
},
"state": {
"value": "MA"
},
"createdate": {
"value": "1380897795295"
},
"hs_analytics_revenue": {
"value": "0.0"
},
"lastname": {
"value": "Mott"
},
"company": {
"value": "HubSpot"
}
},
"form-submissions": [],
"identity-profiles": []
},
"form-submissions": [],
"identity-profiles": []
},
**next similar entry**
Then I try to bind with List of this:
public class HubSpotEmailRqst
{
public int vid { get; set; }
public int canonical-vid { get; set; }
public int portal-id { get; set; }
public bool is-contact { get; set; }
public String profile-token { get; set; }
public String profile-url { get; set; }
public Dictionary<string, string> properties { get; set; }
public Dictionary<string,string> form-submissions { get; set; }
public Dictionary<string,string> identity-profiles { get; set; }
}
I am not sure this will bind either, but I cannot get past the fact we cannot have hyphen in the field names, how can I get around this?
There're two ways to use properties with hyphens:
Name properties according to C# rules, but decorate them with [JsonProperty("property-name")] attribute.
Use custom contract resolver which modifies property names. For example, if all properties in JSON are named consistently, you can use regex to change PascalCase C# property names to lower-case JSON property names. See CamelCasePropertyNamesContractResolver from Json.NET for example implementation.
If I'm understanding the question correctly, you are upset that you can't use a hyphen in a field name in a C# program? Why not use CamelCase to identify the fields? Instead of is-contact use 'isContact'. Instead of canonical-vid. use canonicalVid. Sure, the names may look different, but to the programmer the meaning should be clear.

Categories

Resources