JsonConvert.Deserializer indexing issues
It seems like the stack is being serialized as a List. The problem is that this does not preserve the proper order when deconstructing the stack (the items are actually pushed in the reverse order). Here's a quick workaround to this issue:
using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace StackCollection
{
class Program
{
static void Main(string[] args)
{
Progress progress = new Progress();
progress.Items.Push(new Item { PlanID = null, PlanName = "Plan A" });
var jsonString = JsonConvert.SerializeObject(progress);
var temp = JsonConvert.DeserializeObject<Progress>(jsonString);
temp.Items.Push(new Item { PlanID = null, PlanName = "Plan B" });
jsonString = JsonConvert.SerializeObject(temp);
temp = JsonConvert.DeserializeObject<Progress>(jsonString);
temp.Items.Push(new Item { PlanID = null, PlanName = "Plan C" });
jsonString = JsonConvert.SerializeObject(temp);
temp = JsonConvert.DeserializeObject<Progress>(jsonString);
WriteLine(temp.Items.Peek().PlanName);
ReadLine();
}
}
class Progress
{
[JsonIgnore]
public Stack<Item> Items { get; set; }
public List<Item> ItemList { get; set; }
[OnSerializing]
internal void OnSerializing(StreamingContext context)
{
ItemList = Items?.ToList();
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{
ItemList?.Reverse();
Items = new Stack<Item>(ItemList ?? Enumerable.Empty<Item>());
}
public Progress()
{
Items = new Stack<Item>();
}
}
class Item
{
public string PlanID { get; set; }
public string PlanName { get; set; }
}
}
JsonConvert.DeserializeObject, Index was outside the bounds of the array
From James Newton-King:
A new JsonSerializerInternalReader is created each time you
deserialize an object. Each deserialization happens in its own state.
A high volume server that it deserializing incoming JSON will be
deserializing many many things at the same time without issue.My guess is you have multiple deserializers working over the same
list.
Thanks James. After digging deeper I found that you're right, we were using the same list object for multiple instances of the deserialized type. Specifically, the object looked something like this:
class Obj {
static List<string> _validSelections = new List<string>() { "One", "Two", "Three", "Four" };
public IEnumerable<string> ValidSelections { get { return _validSelections; } }
... more ...
}
The exception was being thrown on line 1261 of JsonSerializerInternalReader.cs when trying to add objects to the list concurrently.
After seeing how this is implemented in our code, I am going to get rid of the static backing since it wasn't providing us anything anyway.
Json.NET can't Deserialize Indexed Property into Array
There is not an attribute in Json.Net that will directly convert your fluffy object into a list, but you can make a custom JsonConverter
to do it without too much trouble, then decorate your Data
class with an attribute to tell Json.Net to use the converter.
Here is what the converter might look like. Note that if there happen to be any gaps in the sequence of Fluff_n
keys, this code will still maintain their relative order in the resulting list, but the gaps will not be preserved. I'm guessing this won't be an issue, but just FYI.
class FluffDataConverter : JsonConverter
{
readonly int PrefixLength = "Fluff_".Length;
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Data));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
List<Thing> things = jo.Properties()
.OrderBy(p => int.Parse(p.Name.Substring(PrefixLength)))
.Select(p => p.Value.ToObject<Thing>())
.ToList();
return new Data { Things = things };
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
To use this converter, just place a [JsonConverter]
attribute on your Data
class like this:
[JsonConverter(typeof(FluffDataConverter))]
public class Data
{
public List<Thing> Things { get; set; }
}
When you re-rerun your test code, it should work as you described.
Json.Net deserialize JSON objects with index as name
You don't need FeaturedArticles
class, you can deserialize the JSON into a Dictionary<string, Articles>
like this:
private void fetchFeaturedArticles()
{
var client = new RestClient (_featuredArticlesJsonUrl);
var request = new RestRequest (Method.GET);
var response = client.Execute (request);
Dictionary<string, Articles> _featuredArticles = JsonConvert.DeserializeObject<Dictionary<string, Articles>>(response.Content);
foreach (string key in _featuredArticles.Keys)
{
Console.WriteLine(_featuredArticles[key].Title);
}
}
Demo: https://dotnetfiddle.net/ZE1BMl
JSON.Net Deserialization error, My Class definition is wrong?
you have to use list of objects, not an object
Dim oResult = JsonConvert.DeserializeObject(Of List(Of MCMusicElements))(sRB)
dtDataTable.Rows(index).Item(1) = oResult(0).MIK_Energy
Error when deserializing JSON to Object
The real issue here is that you are trying to deserialize into a List<object>
but your JSON actually represents a single object containing a data
property which then contains a list of objects. That is why you are getting this error. Json.Net can't deserialize a single object into a list. I think what you really want to do is define a container class like this:
class Root
{
public List<Dictionary<string, object>> Data { get; set;}
}
Then deserialize like this:
var data = JsonConvert.DeserializeObject<Root>(jsonData).Data;
You will then end up with a list of dictionaries, where each dictionary represents one item in the JSON array. The dictionary key-value pairs are the dynamic values in each item. You can then work with these as you would with any other dictionary. For example, here is how you would dump out all the data:
foreach (var dict in data)
{
foreach (var kvp in dict)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
Console.WriteLine();
}
Fiddle: https://dotnetfiddle.net/6UaKhJ
Error Deserializing JSON Object/Array using newtonsoft
Look at Camilo Martinez answer on this discussion :
Deserializing JSON when sometimes array and sometimes object
Basically, you'll need to add the JsonConverter
attribute to your BookingInfo
property and handle the conversion in a JsonConverter
implementation.
public class FlightOptionsList
{
public List<FlightOption> FlightOption { get; set; }
}
public class FlightOption
{
public string LegRef { get; set; }
public string Destination { get; set; }
public string Origin { get; set; }
public Option Option { get; set; }
}
public class Option
{
public string Key { get; set; }
public string TravelTime { get; set; }
[JsonConverter(typeof(SingleValueArrayConverter<BookingInfo>))]
public List<BookingInfo> BookingInfo { get; set; }
public Connection Connection { get; set; }
}
public class BookingInfo
{
public string BookingCode { get; set; }
public string BookingCount { get; set; }
public string CabinClass { get; set; }
public string FareInfoRef { get; set; }
public string SegmentRef { get; set; }
}
public class Connection
{
public string SegmentIndex { get; set; }
}
And here's the converter :
public class SingleValueArrayConverter<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)
{
object retVal = new Object();
if (reader.TokenType == JsonToken.StartObject)
{
T instance = (T)serializer.Deserialize(reader, typeof(T));
retVal = new List<T>() { instance };
}
else if (reader.TokenType == JsonToken.StartArray)
{
retVal = serializer.Deserialize(reader, objectType);
}
return retVal;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
Newtonsoft JSON.NET Deserialization error
You must browse through Response<>
and MyEntity
and see how collections are initialized. This tells us that one of the collections in some class is created using Where
method from linq. You can reproduce this error by executing this code:
class MyEntity
{
public MyEntity()
{
Data = new List<string>().Where(x => true);
}
public IEnumerable<string> Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
string data = @"[{""Data"":[""a"",""b""]}]";
var j = JsonConvert.DeserializeObject<IEnumerable<MyEntity>>(data);
}
}
Another possibility is to have metadata in json. Then you have 2 solutions:
- Set
TypeNameHandling
toTypeNameHandling.None
(as somebody mentioned in comment); - Replace not working types in string with working ones
Using TypeNameHandling.None
may lead to wrong deserialization for exmaple when you have IEnumerable<BaseType>
and that list contains subtype of BaseType
.
In that case you should go for second option. Basically you should replace any type that is not deserializing and replace it for example with List
.
Sample code:
class MyEntity
{
public IEnumerable<string> Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
IList<MyEntity> entities = new MyEntity[] {
new MyEntity { Data = new [] { "1", "2" }.Where(x => x != string.Empty) },
new MyEntity { Data = new [] { "A", "B" }.AsQueryable().Where(x => x != string.Empty) },
new MyEntity { Data = new List<string> { "A", "B" } },
};
string data = JsonConvert.SerializeObject(entities, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
data = Regex.Replace(data, "\"\\$type\":\\s+\"System.Linq.Enumerable\\+WhereArrayIterator(.+?), System.Core\",", "\"$type\": \"System.Collections.Generic.List$1, mscorlib\",", RegexOptions.Singleline);
var j = JsonConvert.DeserializeObject<IEnumerable<MyEntity>>(data, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
}
}
Newtonsoft.Json Deserialize fails
The problem was that my class had a non default constructor and no default constructor. The error message is irrelevant.
Related Topics
Comboboxes Are Linked for Some Reason
Center Messagebox in Parent Form
Httpcontext.Current Is Null When Unit Test
Convert Datatable to Ienumerable<T>
Current Possibilities for Tracing Program Flow in C#
Convert Array of Strings to List<String>
Contextswitchdeadlock Was Detected Error in C#
How to Dynamically Change Auto Complete Entries in a C# Combobox or Textbox
What Is the Default Value for Enum Variable
Converting an Int[] to Byte[] in C#
Working with C# Anonymous Types
Get the Sourcecontrol of a Dropdownmenu
In C# What Category Does the Colon ":" Fall Into, and What Does It Really Mean
Explicitly Freeing Memory in C#
Can Connect to Ftp Using Filezilla or Winscp, But Not with Ftpwebrequest or Fluentftp