Converting JSON into C# object classses - c#

I have a JSON which basically looks like this:
{
"body":
{
"mode": "raw",
"raw": "{
\"Token\" : \"123123\", \"queryName\" : \"testMethod\" ,\"dataTestToSEND\" :{\"IDs\":[\"B00448MZUW\",\"B071F7LBN6\",\"B01BBZJZHQ\"],\"Marketplace\":\"southAmerica\",\"Region\":\"West\",\"PricingMethod\":0}} "a
},
"description": "some description here"
}
}
And when I converted it to C# object classes I got this:
public class Body
{
public string mode { get; set; }
public string raw { get; set; }
}
public class RootObject
{
public Body body { get; set; }
public string description { get; set; }
}
I used json2csharp tool here..
Now what confuses me here is the "raw" property as you can see.. The tool converted it into a string, but this doesn't really looks like a string to me?
Rather a raw, the way I see it, should be an class which contains something like this:
public class Raw
{
public string Token { get; set; }
public string queryName { get; set; }
public List<string//?not sure which type does this needs to be set to?>
dataTestToSEND { get; set }
public string marketplace { get; set; }
public string Region { get; set }
}
Can someone help me out with this? How can I structure a proper set of classes and objects for this JSON? It's very confusing for me right now...

You can use JSON.NET to convert your json to specific class
Official-site: http://www.newtonsoft.com/json
You can remove backslashes from json to let JObject interpret it.
public class Raw
{
public Raw(string json)
{
JObject jObject = JObject.Parse(json);
JToken jRaw = jObject["raw"];
Token = (string) jRaw["token"];
queryName = (string) jRaw["queryName"];
dataTestToSEND = (List<string>) jRaw["dataTestToSEND"];
marketplace = (string) jRaw["Marketplace"]
Region= jRaw["players"].ToArray();
}
public string Token {get;set;}
public string queryName {get;set;}
public List<string> dataTestToSEND {get;set}
public string marketplace {get;set;}
public string Region{get;set}
}
// Call User with your json
string json = #"{""body"":{""mode"":""raw"",""raw"":{""Token"":""123123"",""queryName"":""testMethod"",""dataTestToSEND"":{""IDs"":[""B00448MZUW"",""B071F7LBN6"",""B01BBZJZHQ""],""Marketplace"":""southAmerica"",""Region"":""West"",""PricingMethod"":""0""}}},""description"":""somedescriptionhere""}";
Raw raw = new Raw(json);

json2csharp converted your raw property to a string because it is not able to parse correctly JSON documents with escape characters.
Remove the escape characters in order to let json2csharp create the right sharp class.
{"body":{"mode":"raw","raw":{"Token":"123123","queryName":"testMethod","dataTestToSEND":{"IDs":["B00448MZUW","B071F7LBN6","B01BBZJZHQ"],"Marketplace":"southAmerica","Region":"West","PricingMethod":0}}},"description":"somedescriptionhere"}

Build a custom converter to convert from a string property to a type
public class RawConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.String)
{
throw new InvalidOperationException();
}
var value = (string)reader.Value;
var obj = JsonConvert.DeserializeObject(value, objectType);
return obj;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var str = JsonConvert.SerializeObject(value);
writer.WriteValue(str);
}
}
and put an attribute on the property where you need that converter
public class Body
{
public string mode { get; set; }
// This property is a raw string in the json document
[JsonConverter(typeof(RawConverter))]
public Data raw { get; set; }
}
public class RootObject
{
public Body body { get; set; }
public string description { get; set; }
}
public class Data
{
public string Token { get; set; }
public string queryName { get; set; }
public DataTestToSEND dataTestToSEND { get; set; }
}
public class DataTestToSEND
{
public string[] IDs { get; set; }
public string Marketplace { get; set; }
public string Region { get; set; }
public int PricingMethod { get; set; }
}
and now you can deserialize the given json
{
"body": {
"mode": "raw",
"raw": "{\"Token\":\"123123\",\"queryName\":\"testMethod\",\"dataTestToSEND\":{\"IDs\":[\"B00448MZUW\",\"B071F7LBN6\",\"B01BBZJZHQ\"],\"Marketplace\":\"southAmerica\",\"Region\":\"West\",\"PricingMethod\":0}}"
},
"description": "some description here"
}
with
var result = JsonConvert.DeserializeObject<RootObject>( jsonString );
Live example on .net fiddle with deserialization and serialization

Related

Deserialize JSON where the property name indicates the type of the value

I'm currently dealing with getting data from an external API. The data I receive looks something like what is shown below. (Just a mockup; don't expect the values to make any sense. It's just to illustrate what kind of data I get.)
{
"user": [
{
"key": "12345678",
"data": [
{
"id": "Name",
"string": "Bob"
},
{
"id": "ElapsedTimeSinceLastMessage",
"timestamp": 1618233964000
},
{
"id": "Age",
"number": 27
}
]
}
]
}
I don't really know how I should be going about deserializing this JSON.
The classes I'm using to deserialize right now look like this:
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<DataEntry> DataEntries { get; set; }
}
public class DataEntry
{
[JsonProperty("id")]
public string Id { get; set; }
public Type Value { get; set; }
}
And I don't know what I need to set in order to deserialize the Value inside the DataEntry. Maybe someone can guide me into the right direction?
The Data part of this JSON is really just a Dictionary<string, object> in disguise. You can use a custom JsonConverter to transform the list of id/value pairs into that format for easy use.
Frist, define these classes:
class RootObject
{
[JsonProperty("user")]
public List<User> Users { get; set; }
}
class User
{
public string Key { get; set; }
[JsonConverter(typeof(CustomDataConverter))]
public Dictionary<string, object> Data { get; set; }
}
Next, define the converter:
class CustomDataConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Dictionary<string, object>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return JToken.Load(reader)
.Children<JObject>()
.ToDictionary(jo => (string)jo["id"],
jo => jo.Properties()
.Where(jp => jp.Name != "id" && jp.Value is JValue)
.Select(jp => ((JValue)jp.Value).Value)
.FirstOrDefault());
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
You can then deserialize and dump out the data like this:
var root = JsonConvert.DeserializeObject<RootObject>(json);
foreach (User user in root.Users)
{
Console.WriteLine("User Key: " + user.Key);
foreach (var kvp in user.Data)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
}
Here is a working demo: https://dotnetfiddle.net/GIT4dl
One angle of attack would be with Dictionaries:
public class WithUser
{
public List<User> User { get; set; }
}
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<Dictionary<string,object>> DataEntries { get; set; }
}
The extraction is a bit of a pain but possible:
public static void Main()
{
var json = File.ReadAllText("Example.json");
var x = JsonConvert.DeserializeObject<WithUser>(json);
var user = x.User.Single();
var age = Extract<long>(user, "Age");
var name = Extract<string>(user, "Name");
var elapsedTimeSinceLastMessage = TimeSpan.FromTicks(Extract<long>(user, "ElapsedTimeSinceLastMessage"));
}
public static T Extract<T>(User user, string name)
{
var o = user.DataEntries
.SingleOrDefault(d => (string)d["id"] == name) // Find the one with age
.SingleOrDefault(kvp => kvp.Key != "id") // Find the not 'id' value
.Value; // Take the value
return (T)o;
}
The main issue is in the models that you created.
First of all, base on the JSON, you need another class that contains a list of Users.
public class ResultClass
{
public List<User> User { get; set; }
}
After that, because the second object of data property has not a constant name, we can't specify a constant name for it (like value). We should define the data property as an object. So the user class should be like this:
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<object> DataEntries { get; set; }
}
In the end, in the controller, you should deserialize the ResultJson class:
var result = JsonConvert.DeserializeObject<ResultClass>(jsonTxt);
You can use Json to C#. It generates following classes from your json string. As you can see, you can also use nullable types(long?, int?). If there is a value, sets the required variable. Otherwise leaves it as null. In this way, you can get your different type according to id of data.
public class DataEntry
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("string")]
public string String { get; set; }
[JsonProperty("timestamp")]
public long? Timestamp { get; set; }
[JsonProperty("number")]
public int? Number { get; set; }
}
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<DataEntry> Data { get; set; }
}
public class Root
{
public List<User> User { get; set; }
}
To Deserialize:
string response = "{\"user\":[{\"key\":\"12345678\",\"data\":[{\"id\":\"Name\",\"string\":\"Bob\"},{\"id\":\"ElapsedTimeSinceLastMessage\",\"timestamp\":1618233964000},{\"id\":\"Age\",\"number\":27}]}]}";
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(response);

C# How to save part of nested JSON into object property, but not deserialized?

This is my JSON
{
"type": "user_settings",
"created_at": 1610973280043,
"data": {
"user_id": 12345,
"updated_at": "2021-01-18T15:34:40+03:00"
}
}
These are my classes:
public class BaseMessage
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("created_at")]
public long CreatedAt { get; set; }
[JsonProperty("data")]
public DataDTO Data { get; set; }
public string DataJson {get; set;} // <-- Here I need string like this "{ "user_id": 12345, "updated_at": "2021-01-18T15:34:40+03:00" }"
}
public class DataDTO
{
[JsonProperty("user_id")]
public int UserId { get; set; }
[JsonProperty("updated_at")]
public DateTime? UpdatedAt { get; set; }
}
So I need parsed "data" (it works ok) and save nested JSON as a string (I don't know how).
Is there elegant way to save nested JSON into string property?
Something like this:
public class BaseMessage
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("created_at")]
public long CreatedAt { get; set; }
[JsonProperty("data")]
public DataDTO Data { get; set; }
[JsonPropertyAsString("data")] // <-- This is my fantasy :)
public string DataJson {get; set; }
}
As #dbc commented you can create a custom JsonConverter for the DataJson property, but you also should do something with your another property which is mapped from the data JSON field - Data of DataDTO type. I can propose the following solution:
1. Custom JSON Converter (I took this from #dbc's answer)
public class RawConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var raw = JRaw.Create(reader);
return raw.ToString();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var s = (string)value;
writer.WriteRawValue(s);
}
}
2. Decorate your DataJson property with the JsonConverter attribute and remove JsonPropertyAttribute for the Data property
Note that if you don't remove the JsonPropertyAttribute then it won't work, since you have two properties which are mapped from the same JSON field, and as I know this is not supported by Json.NET by default.
public class BaseMessage
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("created_at")]
public long CreatedAt { get; set; }
public DataDTO Data { get; set; }
[JsonProperty("data")]
[JsonConverter(typeof(RawConverter))]
public string DataJson {get; set;}
}
3. Update your BaseMessage class so this calculates the value of the Data property from DataJson
public class BaseMessage
{
private DataDTO data;
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("created_at")]
public long CreatedAt { get; set; }
public DataDTO Data
{
if (data == null)
{
data = JsonConvert.DeserializeObject<DataDTO>(DataJson);
}
return data;
}
[JsonProperty("data")]
[JsonConverter(typeof(RawConverter))]
public string DataJson {get; set;}
}
Note that I believe this is not the best solution and sure that there are other much better alternatives, but it might be feasible in your case.
Do you mean to use this ??
var data = Newtonsoft.Json.JsonConvert.SerializeObject(object);
if yes, install the newtonSoft packge.

Deserialize Object List Json

I'm new in C# and I want to get a JSON from my app in heroku. Before I did it in javascript with no problems but I'm triying to do it in C# now.
My code is:
namespace FirstApp
{
public class AOA
{
public Data data { get; set; }
public static void Main()
{
var json = string.Empty;
var aoa = new List<AOA>();
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"http://beautyglam.herokuapp.com/aoa/eyeliner?page=1");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
json = reader.ReadToEnd();
aoa = JsonConvert.DeserializeObject<List<AOA>>(json);
Console.WriteLine("DATOS");
Console.WriteLine(json);
Console.WriteLine(aoa[0].data);
}
catch(Exception e)
{
Console.WriteLine("Errorrr: " + e);
}
}
}
public class Data
{
public string category { get; set; }
public int pages { get; set; }
public string name { get; set; }
public int? price { get; set; }
public string id { get; set; }
public string img { get; set; }
}
}
The returned json is something like:
[{"category":"AOA Eye Liner","pages":0},{"name":"AOA Starlet Eyeliner- Spotlight","price":150,"id":"751612657678","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-164-MAIN_large.jpg?v=1539192189"},{"name":"AOA Starlet Eyeliner- Hollywood","price":150,"id":"751612592142","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-166-MAIN_large.jpg?v=1539192156"},{"name":"AOA Starlet Eyeliner- Fame","price":150,"id":"751612559374","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-169-MAIN_large.jpg?v=1539192087"},{"name":"AOA Starlet Eyeliner- Superstar","price":150,"id":"751612526606","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-167-MAIN_large.jpg?v=1539192203"},{"name":"AOA Starlet Eyeliner- Paparazzi","price":150,"id":"751612461070","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-165-MAIN_large.jpg?v=1539192338"},{"name":"AOA Starlet Eyeliner- Golden Girl","price":150,"id":"751612329998","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-168-MAIN_large.jpg?v=1539192127"},{"name":"AOA Wonder Liquid Liner - Black","price":150,"id":"194917793806","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-036-1_large.jpg?v=1522944978"},{"name":"AOA Wonder Liquid Liner - Dark Brown","price":150,"id":"194917335054","img":"//cdn.shopify.com/s/files/1/0882/6874/products/AOA-037-1_large.jpg?v=1522944879"}]
I want to use it like in Javascript, for example:
aoa[0].name;
Your class representation of your json structure is not valid for your example. Also, your json structure needs to be parsed with some special deserializer because it is not contains consist values.
You have an array of json object but they are not have same type.
You need 3 classes which one represents category and pages, one represents name,price,id,img and one for the root which containts those two classes.
Here is what it should look like:
class RootObj {
public Category category { get; set; }
public List<Detail> details { get; set; }
}
class Category {
public string category { get; set; }
public int pages { get; set; }
}
class Detail {
public string name { get; set; }
public int price { get; set; }
public string id { get; set; }
public string img { get; set; }
}
Here is custom deserializer:
class CustomObjectConverter<T> : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
RootObj result = new RootObj();
result.category = array[0].ToObject<Category>();
array.RemoveAt(0);
result.details = array.ToObject<List<Detail>>();
return result;
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(RootObj));
}
}
Main :
string jsonText = File.ReadAllText("json.txt");
var deserializer = new JsonSerializerSettings();
deserializer.Converters.Add(new CustomObjectConverter<RootObj>());
var result = JsonConvert.DeserializeObject<RootObj>(jsonText, deserializer);
Now you can access the properties as :
Console.WriteLine(result.category.category);
Output is :
AOA Eye Liner
You can customize it according to your use cases.

newtonsoft.json deserializing logic

I'm trying to parse a json string with for example [1,2,3] to an array during deserializing.
This is my json data:
[
{
"id": "1",
"district": "1",
"lon": "4.420650000000000000",
"lat": "51.21782000000000000",
"bikes": "19",
"slots": "14",
"zip": "2018",
"address": "Koningin Astridplein",
"addressNumber": null,
"nearbyStations": "3,4,5,24",
"status": "OPN",
"name": "001- Centraal Station - Astrid"
}
]
And this is my c# currently mapping to a regular string, which i would like to be an array of integers.
var AvailabilityMap = new[] { new Station() };
var data = JsonConvert.DeserializeAnonymousType(json, AvailabilityMap);
public class Station
{
public int Id { get; set; }
public double Lon { get; set; }
public double Lat { get; set; }
public int Bikes { get; set; }
public int Slots { get; set; }
public string Address { get; set; }
public string NearbyStations { get; set; }
public string Status { get; set; }
public string Name { get; set; }
}
I have found no way so far to do this in a proper way, without looping trough my current array once more..
Create a custom converter. Something like this:
public class StringToIntEnumerable : JsonConverter
{
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override bool CanWrite
{
get
{
return false; // we'll stick to read-only. If you want to be able
// to write it isn't that much harder to do.
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Note: I've skipped over a lot of error checking and trapping here
// but you might want to add some
var str = reader.Value.ToString();
return str.Split(',').Select(s => int.Parse(s));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Now change you class to use the converter by using the JsonConverterAttribute:
public class Station
{
public int Id { get; set; }
public double Lon { get; set; }
public double Lat { get; set; }
public int Bikes { get; set; }
public int Slots { get; set; }
public string Address { get; set; }
[JsonConverter(typeof(StringToIntEnumerable))]
public IEnumerable<int> NearbyStations { get; set; } // or List<int> or int[] if
// you prefer, just make
// sure the convert returns
// the same type
public string Status { get; set; }
public string Name { get; set; }
}
And now to deserialize:
var stations = JsonConvert.DeserializeObject<List<Station>>(json);
Here is a working fiddle that uses a custom JsonConverter.
What we're doing is converting your CSV values into a proper JSON array before we convert the entire JSON string into a Station object.
Custom JsonConverter
ReadJson reads through the JSON string. First, it loads the JSON into a JObject. Next, it gets the nearbyStations property and changes it from a simple CSV string into a JavaScript array. It does this by wrapping the CSV within square brackets. Finally, we use the JsonSerializer to populate our target object and return it.
CanWrite is set to false, because this JsonConverter is only allowed to read JSON not write to JSON. As a result, we don't need to implement WriteJson. The CanConvert tests to make sure that the target object is a Station.
public class StationConverter : JsonConverter
{
public override object ReadJson(
JsonReader r, Type t, object v, JsonSerializer s)
{
JObject jObject = JObject.Load(r);
var prop = jObject.Property("nearbyStations");
var wrapped = string.Format("[{0}]", prop.Value);
JArray jsonArray = JArray.Parse(wrapped);
prop.Value = jsonArray;
var target = new Station();
s.Populate(jObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter w, object v, JsonSerializer s)
{
throw new NotImplementedException("Unnecessary: CanWrite is false.");
}
public override bool CanWrite
{
get { return false; }
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof (Station);
}
}
Change the Station Class to have an int[]
For the above JsonConverter to to work, change your NearbyStations property to be an int[].
public int[] NearbyStations
{
get;
set;
}
Usage Example with Live Fiddle
Here is an example of how to use it:
var AvailabilityMap =
JsonConvert.DeserializeObject<Station[]>(json, new StationConverter());
Console.WriteLine(AvailabilityMap[0].NearbyStations[0]);
The right answer is to have properly formatted input. In this case:
"nearbyStations": ["3","4","5","24"]
But I was faced with a similar situation in which the data could not be updated, so a solution had to be found. The easiest is to make a getter/setter that won't be touched by the serializer/deserializer. Unfortunately you can't ignore public properties with this serializer out of the box. So you have to do some clever work-arounds like reading into a DTO and using a business object for actual operations.
public class StationDTO
{
public int Id { get; set; }
public double Lon { get; set; }
public double Lat { get; set; }
public int Bikes { get; set; }
public int Slots { get; set; }
public string Address { get; set; }
public string NearbyStations { get; set; }
public string Status { get; set; }
public string Name { get; set; }
}
...
public class Station : StationDTO
{
public List<string> NearbyStationsList
{
get
{
return NearbyStations.Split(',');
}
set
{
NearbyStations = string.Join(",", value);
}
}
}
More information: Newtonsoft ignore attributes?

How to cleanly deserialize JSON where string values are wrapped in objects of the same name

I want to deserialize some strange JSON to C# classes:
{
"Result": {
"Client": {
"ProductList": {
"Product": [
{
"Name": {
"Name": "Car polish"
}
}
]
},
"Name": {
"Name": "Mr. Clouseau"
},
"AddressLine1": {
"AddressLine1": "Hightstreet 13"
}
}
}
}
json2csharp generates the following classes for the JSON:
public class Name
{
public string Name { get; set; }
}
public class Product
{
public Name Name { get; set; }
}
public class ProductList
{
public List<Product> Product { get; set; }
}
public class Name2
{
public string Name { get; set; }
}
public class AddressLine1
{
public string AddressLine1 { get; set; }
}
public class Client
{
public ProductList ProductList { get; set; }
public Name2 Name { get; set; }
public AddressLine1 AddressLine1 { get; set; }
}
public class Result
{
public Client Client { get; set; }
}
public class RootObject
{
public Result Result { get; set; }
}
The problem is that the duplicated property names in the objects (Name in Product and Client, AddressLine1 in Client) forces me to create an extra class with only one string property (Name, AddressLine1) to be able to deserialize the JSON.
The generated code is also invalid, because member names cannot be the same as their enclosing type (but I know that can be solved using the [JsonProperty(PropertyName = "Name")] attribute).
What's the best way to avoid that unnecessary level in the class hierarchy and have a clean class structure to be able to deserialize this JSON using JSON.NET? Note this is a third-party API, so I can't just change the JSON.
Indeed, this is a strange format for an API result, making it more difficult to consume. One idea to solve the problem is to create a custom JsonConverter that can take a wrapped value and return the inner value as if the wrapper were not there. This would allow you to deserialize the clunky JSON into a more sensible class hierarchy.
Here is a converter that should work:
class WrappedObjectConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
// Get the value of the first property of the inner object
// and deserialize it to the requisite object type
return token.Children<JProperty>().First().Value.ToObject(objectType);
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Armed with this converter, you can create a class hierarchy that eliminates the extra levels of nesting. You must mark the properties that need to be "unwrapped" with a [JsonConverter] attribute so that Json.Net knows when to apply the custom converter. Here is the improved class structure:
public class RootObject
{
public Result Result { get; set; }
}
public class Result
{
public Client Client { get; set; }
}
public class Client
{
[JsonConverter(typeof(WrappedObjectConverter))]
public List<Product> ProductList { get; set; }
[JsonConverter(typeof(WrappedObjectConverter))]
public string Name { get; set; }
[JsonConverter(typeof(WrappedObjectConverter))]
public string AddressLine1 { get; set; }
}
public class Product
{
[JsonConverter(typeof(WrappedObjectConverter))]
public string Name { get; set; }
}
(Note that if the Result object will not contain any other properties besides Client, you can apply the WrappedObjectConverter there as well to move the Client up to the RootObject and eliminate the Result class.)
Here is a demo showing the converter in action:
class Program
{
static void Main(string[] args)
{
string json = #"
{
""Result"": {
""Client"": {
""ProductList"": {
""Product"": [
{
""Name"": {
""Name"": ""Car polish""
}
}
]
},
""Name"": {
""Name"": ""Mr. Clouseau""
},
""AddressLine1"": {
""AddressLine1"": ""Hightstreet 13""
}
}
}
}";
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Client client = obj.Result.Client;
foreach (Product product in client.ProductList)
{
Console.WriteLine(product.Name);
}
Console.WriteLine(client.Name);
Console.WriteLine(client.AddressLine1);
}
}
Output:
Car polish
Mr. Clouseau
Hightstreet 13
It sounds like you may be interesting in implementing a custom JsonConverter. Here's a site that has some samples of how you could do this. It's a fairly simple process and would allow you to keep the JSON you're stuck with while having whatever class structure you're most comfortable with.

Categories