C# - Unexpected character encountered while parsing value: {. Path '[0].Statistics

26,793

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:

  1. Elaborating your definition of class Stats, then
  2. Using 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.

Share:
26,793

Related videos on Youtube

RyeGuy
Author by

RyeGuy

Updated on July 09, 2022

Comments

  • RyeGuy
    RyeGuy almost 2 years

    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?

    • Flydog57
      Flydog57 over 5 years
      When you used the Stats class, how did you declare the Statistics property? Have you considered making Statistics a Dictionary<string, int>?
    • gunr2171
      gunr2171 over 5 years
      Your Statistics property is a string.
    • RyeGuy
      RyeGuy over 5 years
      @Flydog57 I will try that. One moment...
    • gunr2171
      gunr2171 over 5 years
      Also see: Accessing properties with a dot in their name in case you do use a class.
    • RyeGuy
      RyeGuy over 5 years
      @Flydog57 I receive the error The property 'Statistics' is of type 'Dictionary<string, int>' which is not supported by current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]'
    • paulsm4
      paulsm4 over 5 years
      I don't see anything "obviously" wrong. An MCVE would definitely be helpful.
    • y.luis.rojo
      y.luis.rojo over 5 years
    • RyeGuy
      RyeGuy over 5 years
      @paulsm4 how do I make an MCVE for C#? Is there a jsfiddle equivalent for C#?
    • RyeGuy
      RyeGuy over 5 years
      @y.luis I will try to implement the solution in that answer
    • dbc
      dbc over 5 years
      @RyeGuy - Is there a jsfiddle equivalent for c#? -- yes there is see dotnetfiddle.net
    • Flydog57
      Flydog57 over 5 years
      "Not supported by current database provider" What database? I don't see anything database-y in your post.
    • Dave
      Dave over 5 years
      Changing the Statistics property to Dictionary<string, int> seems to parse the JSON correctly. The error The property 'Statistics' is of type 'Dictionary<string, int>' which is not supported by current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]' seems to be an Entity Framework error which is beyond the original question asked.
    • dbc
      dbc over 5 years
      Is the set of possible statistics fixed, or variable? If the set of identifiers is fixed, you could simply create a class with the relevant statistics and mark them with [JsonProperty("Avatar.Add")] as shown in this answer to How can I parse a JSON string that would cause illegal C# identifiers?. In fact, one way or another this looks to be a duplicate of that question.
    • dbc
      dbc over 5 years
    • paulsm4
      paulsm4 over 5 years
      Q: So, do you know how to "make an MCVE for C#"? It's not just for "asking questions on SO". It's a very powerful debugging/troubleshooting technique that's applicable to ANY kind of problem. Q: Did it help? Is your problem resolved?