Deserialize Object List Json - c#

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.

Related

ReadAsAsync JSON with non-static datamodels into model

The following is a model based on the response from an API (using sample data):
public class SchoolInfoModel
{
public string Name { get; set; }
public string Website { get; set; }
public Address Address { get; set; }
public List<SchoolTypeModel> SchoolTypes { get; set; }
}
The SchoolTypeModel is where I'm stuck. The SchoolType will return a list but the content of the list might contain one other model or two other models or more. Basically a list of a number of different models. But I do not know in advance which models I receive. How do I map these?
Examples of "SchoolType" models I can receive:
public class HighSchoolModel
{
public string Type { get; set; }
public string SubName { get; set; }
public bool BA { get; set; }
public bool CP { get; set; }
public bool HU { get; set; }
public bool MN { get; set; }
public bool TI { get; set; }
}
public class SpecialPurposeSchoolModel
{
public string Type { get; set; }
public string SubName { get; set; }
public bool AH { get; set; }
}
I have a total of about 10 different types of school.
Here's a way you can achieve this with JSON.Net (which means it will work in .NET Framework 4.8). You can create a custom converter to figure out what properties exist in this JSON and use that to determine which type to deserialise to. For example:
public class SchoolTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
=> objectType == typeof(SchoolTypeModel);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
if (obj.ContainsKey("AH"))
{
return obj.ToObject<SpecialPurposeSchoolModel>(serializer);
}
if (obj.ContainsKey("BA"))
{
return obj.ToObject<HighSchoolModel>(serializer);
}
// We have no idea what this is, so panic
throw new Exception("No idea what to do with this value!");
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
// We are only using this to read JSON
throw new NotImplementedException();
}
}
And to read the JSON:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new SchoolTypeConverter());
var result = JsonConvert.DeserializeObject<SchoolInfoModel>(yourJsonString,
settings); // Pass in the settings object we created above

C# Deserialize JSON with Key Name Starting with String

I have some JSON that looks like this:
{
"fs_Unique_Form_Name": {
"title": "Title Text",
"description": "This is the description.",
"code": "123"
},
"stackId": 1,
"stateId": 1,
"timeStamp": "2020-11-04:10.30.48"
}
I am using Newtonsoft.Json to try and deserialize it to a model object, but am having a hard time with the dynamic keys; I'd like to make that property generic if possible since the inner object is always the same.
Here are the models I am trying to use:
public class FormDetail {
[JsonProperty(PropertyName = "title")]
public string Title { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "code")]
public string Code { get; set; }
}
public class FormResponse {
[JsonProperty(PropertyName = "NEED TO FIGURE THIS OUT")]
public FormDetail FormDetail { get; set; }
[JsonProperty(PropertyName = "stackId")]
public int StackId { get; set; }
[JsonProperty(PropertyName = "stateId")]
public int StateId { get; set; }
[JsonProperty(PropertyName = "timeStamp")]
public string TimeStamp { get; set; }
}
I would like to get the whole JSON deserialized into the FormResponse object, but am having difficulty because the fs_Unique_Form_Name key is dynamic after the fs_ portion, but the keys (title, description, code) in that object are static.
Is there a way for me to do something where I can deserialize it to the FormDetail property when the JSON key starts with fs_?
You can do this by making a custom JsonConverter for your FormResponse class. Below is the code you would need for the converter:
public class FormResponseConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(FormResponse);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load the JSON into a JObject so we can inspect it.
JObject obj = JObject.Load(reader);
// Populate all the known properties on a new instance of FormResponse.
FormResponse response = new FormResponse();
serializer.Populate(obj.CreateReader(), response);
// Now find the first property in the JObject whose name starts with "fs_".
// If there is one, use it to populate the FormDetail on the response.
JProperty prop = obj.Properties().FirstOrDefault(p => p.Name.StartsWith("fs_"));
response.FormDetail = prop != null ? prop.Value.ToObject<FormDetail>(serializer) : null;
return response;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
To use the converter, add a [JsonConverter] attribute to your FormResponse class as shown below. You can remove the [JsonProperty] attribute from the FormDetail property as it is not needed.
[JsonConverter(typeof(FormResponseConverter))]
public class FormResponse
{
public FormDetail FormDetail { get; set; }
[JsonProperty(PropertyName = "stackId")]
public int StackId { get; set; }
[JsonProperty(PropertyName = "stateId")]
public int StateId { get; set; }
[JsonProperty(PropertyName = "timeStamp")]
public string TimeStamp { get; set; }
}
Then you can deserialize as you normally would:
var response = JsonConvert.DeserializeObject<FormResponse>(json);
Here is a working demo: https://dotnetfiddle.net/jHyRcK
There are many ways to do it.
For example, let's create a custom reader.
class CustomJsonReader : JsonTextReader
{
public CustomJsonReader(TextReader reader) : base(reader) { }
public override object Value
{
get
{
if (base.TokenType == JsonToken.PropertyName &&
base.Value.ToString().StartsWith("fs_"))
return "FormDetail";
return base.Value;
}
}
}
Use it like this
FormResponse response;
var serializer = JsonSerializer.CreateDefault();
using (var streamReader = new StreamReader("test.json"))
using (var jsonReader = new CustomJsonReader(streamReader))
{
response = serializer.Deserialize<FormResponse>(jsonReader);
}
In this case, the FormDetail property does not need the JsonProperty attribute.

Deserialize JSON Array with No Member Names to C# Object

I am in search a method that deserializes an array (without member names) to a C# object. Working and expected examples are provided and I have seen many similar posts but not quite what I am looking for hence why felt to ask out for some assistance.
Do I need to take the approach of implementing custom deserialization or am I missing out something already existing?
// Deserialize Works This Way
public class Order
{
public string orderNo { get; set; }
public string customerNo { get; set; }
public List<List<double>> items { get; set; }
}
// Expected Covert Type.
public class OrderExpected
{
public string orderNo { get; set; }
public string customerNo { get; set; }
public List<OrderItem> items { get; set; }
}
public class OrderItem
{
public int itemId { get; set; }
public decimal price { get; set; }
public decimal quantity { get; set; }
}
Code I have tried and what I would like to get working:
var json = "{\"orderNo\":\"AO1234\",\"customerNo\":\"C0129999\",\"items\":[[255, 1.65, 20951.60],[266, 1.80, 20000.00],[277, 1.90,0.50]]}";
// Works OK, but ins't what I am after
var order = JsonConvert.DeserializeObject<Order>(json);
// I'd like to get some help to get this approch working.
var orderexpected = JsonConvert.DeserializeObject<OrderExpected>(json);
Further information on items array:
The items array is going to consist of arrays which have fixed length of 3 and values represent itemId, price and quantity respectively.
P.S. I am consuming an API which is out of my control.
this can help you..
public class OrderExpected
{
public string orderNo { get; set; }
public string customerNo { get; set; }
public List<OrderItem> items { get; set; }
}
[JsonConverter(typeof(OrderItemConverter))]
public class OrderItem
{
public int itemId { get; set; }
public decimal price { get; set; }
public decimal quantity { get; set; }
}
public class OrderItemConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.Name.Equals("OrderItem");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
return new OrderItem {
itemId = array[0].ToObject<int>(),
price = array[1].ToObject<decimal>(),
quantity = array[2].ToObject<decimal>()
};
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var orderItem = value as OrderItem;
JArray arra = new JArray();
arra.Add(orderItem.itemId);
arra.Add(orderItem.price);
arra.Add(orderItem.quantity);
arra.WriteTo(writer);
}
}
using..
string jsonString = "{\"orderNo\":\"AO1234\",\"customerNo\":\"C0129999\",\"items\":[[255, 1.65, 20951.60],[266, 1.80, 20000.00],[277, 1.90,0.50]]}";
var objectResult = JsonConvert.DeserializeObject<OrderExpected>(jsonString);
var serializationResult = JsonConvert.SerializeObject(objectResult);
Console.WriteLine(serializationResult);
// output : {"orderNo":"AO1234","customerNo":"C0129999","items":[[255,1.65,20951.6],[266,1.8,20000.0],[277,1.9,0.5]]}
You can use custom JsonConverter for specified property by using attribute: JsonConverter(typeof(YourCustomConverter))
In your case simple examle should looks like this:
public class OrderExpected
{
public string OrderNo { get; set; }
public string CustomerNo { get; set; }
[JsonConverter(typeof(OrderItemConverter))]
public List<OrderItem> Items { get; set; }
}
public class OrderItemConverter : 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)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jArray = JArray.Load(reader);
var result = new List<OrderItem>();
foreach (var arrayItem in jArray)
{
var innerJArray = arrayItem as JArray;
if(innerJArray?.Count != 3)
continue;
result.Add(new OrderItem
{
ItemId = (int) innerJArray[0],
Price = (decimal)innerJArray[1],
Quantity = (decimal)innerJArray[2]
});
}
return result;
}
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
}
And deserialize your json as usual.
var obj = JsonConvert.DeserializeObject<OrderExpected>(json);
Alright, I agree with Levent. I just want to develop this answer!
in Json.Net side use this attribute [JsonExtensionData] when Json string contains properties without property names
[Serializable]
[JsonObject]
public class Price
{
[JsonExtensionData]
public IDictionary<string, JToken> Values { get; set; }
[JsonProperty("vendor")]
public Dictionary<string, string> vendor { get; set; }
}

Converting JSON into C# object classses

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

how do deserialize this json string to class

I have the following json string:
{"Visits":[true,"DockedOnly","leftZone","0","500",0,0,0],
"Weather":[true,"DockedOnly","leftZone","0","0",0,0,1],
"ContactUs":[true,"DockedOnly","leftZone","0","317",0,0,2],
"Birthdays":[true,"DockedOnly","middleZone","0","0",0,0,0],
"Reminders":[true,"DockedOnly","middleZone","0","145",0,0,1],
"Messages":[true,"DockedOnly","middleZone","0","0",0,0,2],
"Availability":[true,"DockedOnly","middleZone","0","0",0,0,3],
"Settings":[false,"DockedOnly","leftzone","0","155",0,0,0]}
Is there anyway to deserialize to something like the following?
[Serializable]
public class WidgetProps
{
public bool Visible { get; set; }
public string DockState { get; set; }
public string Zone { get; set; }
public string Top { get; set; }
public string Left { get; set; }
public int UnusedA { get; set; }
public int UnusedB { get; set; }
public int Position { get; set; }
}
[Serializable]
public class WidgetLayout
{
public WidgetProps Visits { get; set; }
public WidgetProps Weather { get; set; }
public WidgetProps ContactUs { get; set; }
public WidgetProps Birthdays { get; set; }
public WidgetProps Reminders { get; set; }
public WidgetProps Messages { get; set; }
public WidgetProps Availability { get; set; }
public WidgetProps Settings { get; set; }
}
or
public class Widget
{
public string WidgetName { get; set; }
public WidgetProps props { get; set; }
}
List<Widget> MyWidgets;
I am given the json string so I can't change how it is given to me but maybe I could tinker with it after I get it so it will work.
I tried:
string s = "{\"Visits\":[true,\"DockedOnly\",\"leftZone\",\"0\",\"500\",0,0,0],\"Weather\":[true,\"DockedOnly\",\"leftZone\",\"0\",\"0\",0,0,1],\"ContactUs\":[true,\"DockedOnly\",\"leftZone\",\"0\",\"317\",0,0,2],\"Birthdays\":[true,\"DockedOnly\",\"middleZone\",\"0\",\"0\",0,0,0],\"Reminders\":[true,\"DockedOnly\",\"middleZone\",\"0\",\"145\",0,0,1],\"Messages\":[true,\"DockedOnly\",\"middleZone\",\"0\",\"0\",0,0,2],\"Availability\":[true,\"DockedOnly\",\"middleZone\",\"0\",\"0\",0,0,3],\"Settings\":[false,\"DockedOnly\",\"leftzone\",\"0\",\"155\",0,0,0]}}";
var sd = new JavaScriptSerializer().Deserialize < List<Widget>>(s);
and
var sd = new JavaScriptSerializer().Deserialize < WidgetLayout >(s);
This isn't working because you're trying to deserialize an array into an object. The json.NET deserializer will not be able make that conversion.
Because your json arrays have multiple types in them you'll have to deserialize into the smallest common denominator, in this case, object. From there I would recommend writing a method to assign each index to it's corresponding property in WidgetProps.
So basically, define this constructor;
public WidgetProps(object[] props)
{
Visible = (bool)props[0];
DockState = (string)props[1];
// ext
}
I would have something like a WidgetDirty class that I do the initial deserilization into. From there you can create a new instance of WidgetLayout by instantiating each of it's properties like myWidgetLayoutInstance.Visits = new WidgetProp(myWidgetDirtyInstance.Visits); I'd probably hide this mess in a WidgetLayout constructor that takes a WidgetDirty as it's only arg.
yes it's disgusting... but I don't know of any real alternatives because that json's design just isn't very compatible with the C# language. If you're strongly apposed to this I might look at the dynamic type. I haven't used it in C# and probably never will, but I know that deserializing that in a dynamic language like PHP would be no trouble at all.
This doesn't work, because array is normally not deserialized as an object. If possible, I think you should fix the JSON. If you can't do that, and you're using JSON.NET, you can create JsonConverter for WidgetProps that manually converts the array to the object:
class WidgetPropsConverter : JsonConverter
{
public override void WriteJson(
JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}
public override object ReadJson(
JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var array = serializer.Deserialize<object[]>(reader);
return new WidgetProps
{
Visible = (bool)array[0],
DockState = (string)array[1],
Zone = (string)array[2],
Top = (string)array[3],
Left = (string)array[4],
Position = (int)(long)array[7]
};
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(WidgetProps);
}
}
You would then use it like this:
var result = JsonConvert.DeserializeObject<WidgetLayout>(
jsonString, new WidgetPropsConverter());

Categories