Deserializing JSON Object Array with Json.net
You can create a new model to Deserialize your JSON CustomerJson
:
public class CustomerJson
{
[JsonProperty("customer")]
public Customer Customer { get; set; }
}
public class Customer
{
[JsonProperty("first_name")]
public string Firstname { get; set; }
[JsonProperty("last_name")]
public string Lastname { get; set; }
...
}
And you can deserialize your JSON easily:
JsonConvert.DeserializeObject<List<CustomerJson>>(json);
Documentation: Serializing and Deserializing JSON
How to deserialize a JSON array into an object using Json.Net?
Json.Net does not have a facility to automatically map an array into a class. To do so you need a custom JsonConverter
. Here is a generic converter that should work for you. It uses a custom [JsonArrayIndex]
attribute to identify which properties in the class correspond to which indexes in the array. This will allow you to easily update your model if the JSON changes. Also, you can safely omit properties from your class that you don't need, such as Filler
.
Here is the code:
public class JsonArrayIndexAttribute : Attribute
{
public int Index { get; private set; }
public JsonArrayIndexAttribute(int index)
{
Index = index;
}
}
public class ArrayToObjectConverter<T> : JsonConverter where T : class, new()
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(T);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
var propsByIndex = typeof(T).GetProperties()
.Where(p => p.CanRead && p.CanWrite && p.GetCustomAttribute<JsonArrayIndexAttribute>() != null)
.ToDictionary(p => p.GetCustomAttribute<JsonArrayIndexAttribute>().Index);
JObject obj = new JObject(array
.Select((jt, i) =>
{
PropertyInfo prop;
return propsByIndex.TryGetValue(i, out prop) ? new JProperty(prop.Name, jt) : null;
})
.Where(jp => jp != null)
);
T target = new T();
serializer.Populate(obj.CreateReader(), target);
return target;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
To use the converter, you need to mark up your ChildModel
class as shown below:
[JsonConverter(typeof(ArrayToObjectConverter<ChildModel>))]
class ChildModel
{
[JsonArrayIndex(0)]
public int ID { get; set; }
[JsonArrayIndex(1)]
public string StatusId { get; set; }
[JsonArrayIndex(2)]
public DateTime ContactDate { get; set; }
[JsonArrayIndex(3)]
public string State { get; set; }
[JsonArrayIndex(4)]
public string Status { get; set; }
[JsonArrayIndex(5)]
public string CustomerName { get; set; }
[JsonArrayIndex(6)]
public DateTime WorkStartDate { get; set; }
[JsonArrayIndex(7)]
public DateTime WorkEndDate { get; set; }
[JsonArrayIndex(8)]
public string Territory { get; set; }
[JsonArrayIndex(9)]
public string CustType { get; set; }
[JsonArrayIndex(10)]
public int JobOrder { get; set; }
[JsonArrayIndex(12)]
public string Link { get; set; }
}
Then just deserialize as usual and it should work as you wanted. Here is a demo: https://dotnetfiddle.net/n3oE3L
Note: I did not implement WriteJson
, so if you serialize your model back to JSON, it will not serialize back to the array format; instead it will use the default object serialization.
Deserialize json array to c# list object
I am sure that exception is not related to you JSON string but try to remove bin
and obj
from solution folder and then clean and rebuild solution.
but after resolving that you will get the below exception
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'namespace.Order' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.....
Because your JSON string is List of Order
so the deserialize would be change to :
List<Order> ObjOrderList = JsonConvert.DeserializeObject<List<Order>>(orderJson);
or in the other side you can also use JavaScriptSerializer
like:
Order[] orderList = new JavaScriptSerializer().Deserialize<Order[]>(orderJson);
Deserializing an array of objects with Json.Net
If I read your json data structure correctly you would want this:
public class Root
{
public List<Customer> rows { get; set; }
}
and
var data = JsonConvert.DeserializeObject<Root>(val);
Tested code:
void Main()
{
var test = JsonConvert.DeserializeObject<Root>("{\"rows\":[{\"id\":\"232333\",\"name\":\"nam\"},{\"id\":\"3434444\",\"name\":\"2ndName\"}]}");
Console.WriteLine(test.rows[0].id); // prints 232333
}
public class Customer
{
public int id { get; set; }
}
public class Root
{
public List<Customer> rows { get; set; }
}
Deserialize JSON array of arrays into c# class
Since you have only values without properties names in your JSON, you can deserialize it into sequence of collection objects, like IEnumerable<string[]>
, IEnumerable<List<string>>
or List<List<string>>
. Then parse every item to Person
manually (assuming that you have the same structure for all items, otherwise you'll need an additional logic for checking an errors)
var result = JsonConvert.DeserializeObject<IEnumerable<string[]>>(jsonString);
var persons = result
.Select(item => new Person { Name = item[0], Age = int.Parse(item[1]), Car = item[2] })
.ToList();
Deserialize array of array using json .net
you have a double list , so or fix json or use this code
var obj = JsonSerializer.Deserialize<List<List<object>>>(json);
The class should have at least one property. Your json doesnt' have any properties at all, so only array can be used in this case. It can be converted to the class, for example like this
public class MyClass
{
public List<object> Details {get;set;}
}
var jsonParsed = JArray.Parse(json);
List<MyClass> objects = jsonParsed.Select(p => p)
.Select(x => new MyClass { Details=x.ToObject<List<object>>() }).ToList();
now if you want more details you have to convert array to your class,
Each element of array should get name, for example
public class Details
{
public Id {get; set;}
public bool IsActive {get;set}
...and so on
}
after this you can use this class already
public class MyClass
{
public Details Details {get;set;}
}
Deserialize JSON as object or array with JSON.Net
You can change the property type for "data" in your model to dynamic or an object and check if it is an array on run-time.
Here's an example:
public class Response
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("data")]
public dynamic Data { get; set; }
}
var response = JsonConvert.DeserializeJson<Response>(json);
.
.
.
Type responseDataType = response.Data.GetType();
if(responseDataType.IsArray) {
// It's an array, what to do?
}
else {
// Not an array, what's next?
}
Deserialize json object to array
You can create a new class:
public class MyClass {
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("dir")]
public string Dir { get; set; }
[JsonProperty("valid")]
public bool Valid { get; set; }
}
And then just use deserialize:
var data = JsonConvert.DeserializeObject<MyClass[]>(myJsonResponse).Select(x => x.Name).ToArray();
Deserialize json array of array to List of string in C#
You have not only string in your collection and you have nested arrays, so List<string>
does not represent your JSON structure. If you want to get only string you can do something like this (this one is with Newtonsoft, after fixing the d
value):
var strings = JsonConvert.DeserializeObject<List<List<object>>>(json)
.Select(arr => arr.OfType<string>().ToList())
.ToList();
Or using arr => arr.Select(a => a?.ToString()
in Select
if you want to convert all values to strings.
Or you can convert to List<JArray>
with Newtonsoft and call ToString
on it:
List<string> strings = JsonConvert.DeserializeObject<List<JArray>>(json)
.Select(jarr => jarr.ToString(Newtonsoft.Json.Formatting.None))
.ToList();
Console.WriteLine(string.Join(", ", strings)); // prints "["a","b","c",null,1], ["d","e",null,2]"
Newtonsoft Json.Net - How to conditionally add (or skip) items in an array when deserializing?
You can create the following JsonConverter<T []>
that will skip array entries beyond a certain count:
public class MaxLengthArrayConverter<T> : JsonConverter<T []>
{
public MaxLengthArrayConverter(int maxLength) => this.MaxLength = maxLength >= 0 ? maxLength : throw new ArgumentException(nameof(maxLength));
public int MaxLength { get; }
public override T [] ReadJson(JsonReader reader, Type objectType, T [] existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
reader.AssertTokenType(JsonToken.StartArray);
var list = new List<T>();
while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray)
{
if (list.Count < MaxLength)
list.Add(serializer.Deserialize<T>(reader));
else
reader.Skip();
}
return list.ToArray();
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, T [] value, JsonSerializer serializer) => throw new NotImplementedException();
}
public static partial class JsonExtensions
{
public static JsonReader AssertTokenType(this JsonReader reader, JsonToken tokenType) =>
reader.TokenType == tokenType ? reader : throw new JsonSerializationException(string.Format("Unexpected token {0}, expected {1}", reader.TokenType, tokenType));
public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
reader.ReadAndAssert().MoveToContentAndAssert();
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
}
Then, assuming your financial market orderbook model looks something like this:
public class OrderBook
{
public Order [] Orders { get; set; }
}
You can deserialize as follows:
int maxLength = 20; // Or whatever you want.
var settings = new JsonSerializerSettings
{
Converters = { new MaxLengthArrayConverter<Order>(maxLength) },
};
var model = JsonConvert.DeserializeObject<OrderBook>(json, settings);
Assert.IsTrue(model.Orders.Length <= maxLength);
Notes:
In your question you mention only arrays, but if your model is actually using lists rather than arrays, use the following converter instead:
public class MaxLengthListConverter<T> : JsonConverter<List<T>>
{
public MaxLengthListConverter(int maxLength) => this.MaxLength = maxLength >= 0 ? maxLength : throw new ArgumentException(nameof(maxLength));
public int MaxLength { get; }
public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
reader.AssertTokenType(JsonToken.StartArray);
existingValue ??= (List<T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
existingValue.Clear();
while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray)
{
if (existingValue.Count < MaxLength)
existingValue.Add(serializer.Deserialize<T>(reader));
else
reader.Skip();
}
return existingValue;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer) => throw new NotImplementedException();
}This answer assumes that you want all arrays of type
T []
in your model to be truncated to some specific length in runtime. If this is not true, and you need different max lengths for different arrays to be individually specified in runtime, you will need a more complex solution, probably involving a custom contract resolver.
Demo fiddle here.
Related Topics
How to Return a String Repeated X Number of Times
What How to Use for Good Quality Code Coverage for C#/.Net
How to Check for Permissions to Write to a Directory or File
Does C# 8 Support the .Net Framework
Wpf Webbrowser Control - How to Suppress Script Errors
Shouldserialize*() VS *Specified Conditional Serialization Pattern
Why Can't I Inherit Static Classes
Wait Until File Is Completely Written
How to Write a Scalable Tcp/Ip Based Server
Converting a .Net Func<T> to a .Net Expression<Func<T>>
Reflection to Identify Extension Methods
Deserializing JSON Object Array with JSON.Net
How to Get Client Ip Address in ASP.NET Core
Does the C# "Finally" Block Always Execute
Gradient Circles for Map Generator