I am trying to deserialize a JSON object according to my model using the code below:
LoadData<MyModel>(Data.Stats, null);
public void LoadData<TModel>(string data, JsonSerializerSettings jsonSettings) where TModel : class
{
var mockData = JsonConvert.DeserializeObject<Collection<TModel>>(data, jsonSettings); // ERROR HERE
Context.SaveChanges();
}
However I am getting an error that reads
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: {. Path '[0].Statistics', line 7, position 19.'
My JSON object is:
[
{
"Id": 3033,
"Grade": 3,
"Statistics": { //ERROR OCCURS ON THIS PROPERTY
"Avatar.Add": 1,
"TotalPlays": 36,
"Game.TotalPlays.Spell_Mem_Words": 27,
"Book.TotalReads.Count": 23,
"Game.TotalPlays.Count": 39,
"Character.TotalPlays.L": 23,
"Character.TotalPlays.E": 3,
"TotalPlays.Pick_Vocab": 16,
"Character.TotalPlays.R": 22
}
}
]
The Object Model is:
public class MyModel
{
public int Id { get; set; }
public int Grade { get; set; }
public string Statistics { get; set; }
}
Things I Have Tried
(1) Using json lint I have ensured that the json string is valid.
(2) In javascript serializing the object with back ticks surrounding it works. Backticks don't work in C# JS Fiddle
(3) Tried making the Statistics property in object model to use class called stats instead of string like
public class Stats
{
public string Label { get; set;}
public int Value { get; set; }
}
(4) Tried nearly all the answers on this SO post
Unfortunately I still have not solved this issue. Any ideas?
I was able to reproduce the problem with this MCVE:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DeserializeJson
{
/**
* REFERENCE:
* https://stackoverflow.com/questions/53562566/
*
* ORIGINAL ERROR:
* "Unexpected character encountered while parsing value: {. Path '[0].Statistics', line 5, position 19."
*/
public class Stats
{
public string Label { get; set; }
public int Value { get; set; }
}
public class MyModel
{
public int Id { get; set; }
public int Grade { get; set; }
public string Statistics { get; set; }
}
class Program
{
static Collection<MyModel> LoadData(string data)
{
var retval = JsonConvert.DeserializeObject<Collection<MyModel>>(data);
return retval;
}
static void Main(string[] args)
{
try
{
string s = File.ReadAllText(@"test-data.json");
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Formatting = Newtonsoft.Json.Formatting.Indented
};
Collection <MyModel> mockData = Program.LoadData(s);
System.Console.WriteLine("#/items= " + mockData.Count);
foreach (MyModel item in mockData)
{
System.Console.WriteLine(" id= {0}, Grade={1}, Statistics={2}", item.Id, item.Grade, item.Statistics.ToString());
}
}
catch (Exception ex)
{
System.Console.WriteLine("ERROR:", ex);
}
}
}
}
I was able to fix it by:
class Stats
, thenUsing Stats in the definition of class MyModel
:
public class Stats
{
public int AvatarAdd { get; set; }
public int TotalPlays { get; set; }
public int GameTotalPlaysSpellMemWords { get; set; }
public int BookTotalReadsCount { get; set; }
public int GameTotalPlaysCount { get; set; }
public int CharacterTotalPlaysL { get; set; }
public int CharacterTotalPlaysE { get; set; }
public int TotalPlaysPick_Vocab { get; set; }
public int CharacterTotalPlaysR { get; set; }
}
public class MyModel
{
public int Id { get; set; }
public int Grade { get; set; }
public Stats Statistics { get; set; }
}
You have several choices (including use the above example verbatim). My suggestion would be to break "Statistics" down into smaller model classes.