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

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

In My case the issue was the JSON File encoding was chosen as "UTF-8-BOM"
I had to convert that to "UTF-8".
Then it worked fine for me.

Related

How to generate a JSON class with dynamic name

I don't know if there is an existing name for that case, but I'm trying to retrieve data from NASA API (https://api.nasa.gov/) and I have a simple challenge to catch a list of objects near earth. Here is the JSON response I have from the GET request I do to "https://api.nasa.gov/neo/rest/v1/feed?...."
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-04&end_date=2021-07-04&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-02&end_date=2021-07-02&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-03&end_date=2021-07-03&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"element_count": 6,
"near_earth_objects": {
"2021-07-03": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/3701710?api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"id": "3701710",
"neo_reference_id": "3701710",
"name": "(2014 WF497)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3701710",
"absolute_magnitude_h": 20.23,
"estimated_diameter": {
"kilometers": {
}
And that's the way it is built in Visual Studio (using the Special Paste option for JSON)
public class NearEarthObject
{
public Links links { get; set; }
public int element_count { get; set; }
public Near_Earth_Objects near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
public class Near_Earth_Objects
{
public _20210703[] _20210703 { get; set; }
}
public class _20210703
{
public Links1 links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
The question is, inside of the element "near_earth_objects", there is an element called "2021-07-03" (the date of the data I requested), the problem is that I am trying to include it into a DataGridView made in .NET C# (Windows Forms, but that doesn't matters here, I think) and the user wants to get the information by date. So, "2021-07-03" is a valid member just for one day, and the user should be able to get data from multiple days.
So, is there a way in C# to get all child objects inside of near_earth_objects without knowing their names since there will be the option to search for asteroids from date X to Y in my application?
Using System.Text.Json
The API response will map to the following classes
public class Neo
{
public Links Links { get; set; }
public int ElementCount { get; set; }
public Dictionary<string, List<NearEarthObject>> NearEarthObjects { get; set; }
}
public class Links
{
public string Next { get; set; }
public string Prev { get; set; }
public string Self { get; set; }
}
public class NearEarthObject
{
public Links Links { get; set; }
public string Id { get; set; }
public string Name { get; set; }
// Other properties
}
The NearEarthObjects is simply a Dictionary, where the key is the formatted date and value is a List containing NearEarthObject
The PropertyNamingPolicy will allow us to support the API's underscore property naming convention.
public class UnderscoreNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return name.Underscore();
}
}
Example usage
// using using System.Text.Json;
var response = await new HttpClient().GetStringAsync(url);
var neo = JsonSerializer.Deserialize<Neo>(response, new JsonSerializerOptions
{
PropertyNamingPolicy = new UnderscoreNamingPolicy()
});
foreach(var neos in neo.NearEarthObjects)
{
Console.WriteLine(neos.Key);
}
use System.Text.Json, JsonNamingPolicy
demo code
public class DynamicNamePolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
var today = DateTime.Today.ToString("yyyy-MM-dd");
if (name.Equals("DateData")) //model property name
return today; //convert to json string property name
return name;
}
}
//data deserialize
string data = ""; //json string
var obj = JsonSerializer.Deserialize<NearEarthObject>(data, new JsonSerializerOptions
{
PropertyNamingPolicy = new DynamicNamePolicy(),
});

Deserialize JSON to Nested Model

I have a model like below:
public class YourInformationInputModel
{
public YourInformationInputModel()
{
PrimaryBuyerInformation = new PrimaryBuyerInformationInputModel();
}
public PrimaryBuyerInformationInputModel PrimaryBuyerInformation { get; set; }
public bool TermsCondition { get; set; }
}
PrimaryBuyerInputModel like below:
public class PrimaryBuyerInformationInputModel
{
[Required]
public string BuyerFirstName { get; set; }
public string BuyerMiddleInitial { get; set; }
[Required]
public string BuyerLastName { get; set; }
}
and when I am submitting my form then I am getting JSON like below:
{
"PrimaryBuyerInformation.BuyerFirstName": "Sunil",
"PrimaryBuyerInformation.BuyerMiddleInitial": "",
"PrimaryBuyerInformation.BuyerLastName": "Choudhary",
"TermsCondition": "true"
}
When I am trying to deserialize this json the TermsCondition property successfully done, but the property of PrimaryBuyerInformation is not mapped.
var myObject = JsonConvert.DeserializeObject<YourInformationInputModel>(json);
Any idea how to do that ?
Kindly take a cue from the code below, i tested it and you should be able to get your value as request. This solves the issue of you trying to access the property you have mapped in a dot property name format.
Instead your object should be nested in a curly brace showing that the other property belongs to PrimaryBuyerInformationInputModel which is another object entirely.
Best Regards,
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var json = #"{'PrimaryBuyerInformation': {'buyerFirstName': 'Sunil','buyerMiddleInitial': '','buyerLastName': 'Choudhary'},'termsCondition': false}";
var obj = JsonConvert.DeserializeObject<YourInformationInputModel>(json);
Console.WriteLine(obj.PrimaryBuyerInformation.BuyerFirstName);
}
}
public class YourInformationInputModel
{
public YourInformationInputModel()
{
PrimaryBuyerInformation = new PrimaryBuyerInformationInputModel();
}
public PrimaryBuyerInformationInputModel PrimaryBuyerInformation { get; set; }
public bool TermsCondition { get; set; }
}
public class PrimaryBuyerInformationInputModel
{
public string BuyerFirstName { get; set; }
public string BuyerMiddleInitial { get; set; }
public string BuyerLastName { get; set; }
}

Map JSON object to C# class property array

JSON
{
"SoftHoldIDs": 444,
"AppliedUsages": [
{
"SoftHoldID": 444,
"UsageYearID": 223232,
"DaysApplied": 0,
"PointsApplied": 1
}
],
"Guests": [
1,
2
]
}
In the above JSON SoftholdIDs is integer and AppliedUsages is class array property in C# Model
Issue is --How we can map JSON to class property.
Class code
public class ReservationDraftRequestDto
{
public int SoftHoldIDs { get; set; }
public int[] Guests { get; set; }
public AppliedUsage[] AppliedUsages { get; set; }
}
public class AppliedUsage
{
public int SoftHoldID { get; set; }
public int UsageYearID { get; set; }
public int DaysApplied { get; set; }
public int PointsApplied { get; set; }
}
Tried below code for mapping
ReservationDraftRequestDto reservationDto = null;
dynamic data = await reservationDraftRequestDto.Content.ReadAsAsync<object>();
reservationDto = JsonConvert.DeserializeObject<ReservationDraftRequestDto>(data.ToString());
You need to change
dynamic data = await reservationDraftRequestDto.Content.ReadAsAsync<object>();
to
string data = await reservationDraftRequestDto.Content.ReadAsStringAsync();
this will read your response as string
then do
reservationDto = JsonConvert.DeserializeObject<ReservationDraftRequestDto>(data);
this work
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
string json = #"{""SoftHoldIDs"": 444,""AppliedUsages"": [ {""SoftHoldID"": 444,""UsageYearID"": 223232,""DaysApplied"": 0,""PointsApplied"": 1}],""Guests"": [ 1, 2]}";
Rootobject reservationDto = JsonConvert.DeserializeObject<Rootobject>(json.ToString());
Debug.WriteLine(reservationDto.SoftHoldIDs);
foreach (var guest in reservationDto.Guests)
{
Debug.WriteLine(guest);
}
}
}
public class Rootobject
{
public int SoftHoldIDs { get; set; }
public Appliedusage[] AppliedUsages { get; set; }
public int[] Guests { get; set; }
}
public class Appliedusage
{
public int SoftHoldID { get; set; }
public int UsageYearID { get; set; }
public int DaysApplied { get; set; }
public int PointsApplied { get; set; }
}
}
First create class copying json as classwith visualstudio.
Next you have double quote in json respons so deal with it.
Json.NET: Deserilization with Double Quotes

how can I get json data in to the c# object?

Below is my class for the json output:
class PwdResetRequest
{
public class TopScoringIntent
{
public string intent { get; set; }
public double score { get; set; }
}
public class Intent
{
public string intent { get; set; }
public double score { get; set; }
}
public class Resolution
{
public string value { get; set; }
}
public class Entity
{
public string entity { get; set; }
public string type { get; set; }
public int startIndex { get; set; }
public int endIndex { get; set; }
public Resolution resolution { get; set; }
}
public class RootObject
{
public string query { get; set; }
public TopScoringIntent topScoringIntent { get; set; }
public List<Intent> intents { get; set; }
public List<Entity> entities { get; set; }
}
}
Luis Return result:
{
"query": "create a new password for sjao9841#demo.com",
"topScoringIntent": {
"intent": "ResetLANIDpassword",
"score": 0.9956063
},
"intents": [
{
"intent": "ResetLANIDpassword",
"score": 0.9956063
},
{
"intent": "None",
"score": 0.179328963
}
],
"entities": [
{
"entity": "sjao9841#demo.com",
"type": "builtin.email",
"startIndex": 26,
"endIndex": 47
}
]
}
I have developed the below code for getting the data from the json.
var uri =
"https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/" +
luisAppId + "?" + queryString;
var response = await client.GetAsync(uri);
var strResponseContent = await response.Content.ReadAsStringAsync();
var json = await response.Content.ReadAsStringAsync();
var token = JObject.Parse(json).SelectToken("entities");
foreach (var item in token)
{
var request = item.ToObject<Entity>();
}
// Display the JSON result from LUIS
Console.WriteLine(strResponseContent.ToString());
}
And I only want the data from the "TopScoringIntent". How can I get that using C#? Below is the code that I tried but nothing came out:
Message=Error reading JObject from JsonReader. Path '', line 0, position 0.
Source=Newtonsoft.Json
I may be missing your intent, but if you only care about specific value rather than the entire javascript object, you could do the following.
dynamic json = JsonConvert.Deserialize(data);
var score = json.TopScoringIntent.Score;
That provides the specific value of score within TopScoringIntent. Obviously, you could also build a collection also well, by modifying slightly.
foreach(var point in json.Intents)
Console.WriteLine($"{point[1]} or {point.score}");
I believe that is what you're looking for, to receive a specific value from your object. Please note dynamics are useful, but this approach is a fairly quick and dirty, may not be ideal for your implementation.
quicktype generated the following C# classes and JSON.Net marshaling code for your sample data:
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using QuickType;
//
// var pwdResetRequest = PwdResetRequest.FromJson(jsonString);
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using J = Newtonsoft.Json.JsonPropertyAttribute;
public partial class PwdResetRequest
{
[J("query")] public string Query { get; set; }
[J("topScoringIntent")] public Ntent TopScoringIntent { get; set; }
[J("intents")] public Ntent[] Intents { get; set; }
[J("entities")] public Entity[] Entities { get; set; }
}
public partial class Entity
{
[J("entity")] public string EntityEntity { get; set; }
[J("type")] public string Type { get; set; }
[J("startIndex")] public long StartIndex { get; set; }
[J("endIndex")] public long EndIndex { get; set; }
}
public partial class Ntent
{
[J("intent")] public string Intent { get; set; }
[J("score")] public double Score { get; set; }
}
public partial class PwdResetRequest
{
public static PwdResetRequest FromJson(string json) => JsonConvert.DeserializeObject<PwdResetRequest>(json, QuickType.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this PwdResetRequest self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {
new IsoDateTimeConverter()
{
DateTimeStyles = DateTimeStyles.AssumeUniversal,
},
},
};
}
}
Now you can use System.Linq to get the maximum Ntent by Score:
var uri = $"https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/${luisAppId}?${queryString}";
var response = await client.GetAsync(uri);
var json = await response.Content.ReadAsStringAsync();
var request = PwdResetRequest.FromJson(json);
var maxIntent = request.Intents.MaxBy(intent => intent.Score);
Here's the generated code in a playground so you can change the type names and other options.

Convert JSON Object to C# Object

I have a json object and I am trying to convert it to my c# object. Here is my JSON:
{"GuvenlikNoktaArray": {"GuvenlikNoktası": [{"Id": 1,"GuvenlikNoktası1":"SANTIYE","KartNo":"000001889174217","Sira": 1},{"Id": 2,"GuvenlikNoktası1":"INSAAT","KartNo":"000000803567858","Sira": 2},{"Id": 3,"GuvenlikNoktası1":"ÇALISMA","KartNo":"000003417926233","Sira": 3},{"Id": 4,"GuvenlikNoktası1":"GÜVENLIK","KartNo":"000001888909897","Sira": 4}]}}
And my c# class:
public partial class GuvenlikNoktası
{
public GuvenlikNoktası()
{
this.GüvenlikNoktasıOlay = new HashSet<GüvenlikNoktasıOlay>();
this.PanikButonuAlarmlari = new HashSet<PanikButonuAlarmlari>();
}
public int Id { get; set; }
public string GuvenlikNoktası1 { get; set; }
public string KartNo { get; set; }
public string Sira { get; set; }
public virtual ICollection<GüvenlikNoktasıOlay> GüvenlikNoktasıOlay { get; set; }
public virtual ICollection<PanikButonuAlarmlari> PanikButonuAlarmlari { get; set; }
}
And last, my convert try:
public void AddIstasyon(string json_string)
{
GuvenlikNoktası result = new JavaScriptSerializer().Deserialize<GuvenlikNoktası>(json_string);
}
I don't get any errors but when I debuged, I see that all attributes inside 'result' are null. It seems like an empty object. How can I get a correct 'GuvenlikNoktası' object ? (Btw I am pretty sure I am getting the json object correctly).
If you must keep this JSON structure as-is you may use JObject to navigate inside your JSON properties until you reach your target objects to deserizlize. Please can you try the code below;
PS: This code uses Newtonsoft.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SO_39847703
{
class Program
{
static void Main(string[] args)
{
string json = "{\"GuvenlikNoktaArray\": {\"GuvenlikNoktası\": [{\"Id\": 1,\"GuvenlikNoktası1\":\"SANTIYE\",\"KartNo\":\"000001889174217\",\"Sira\": 1},{\"Id\": 2,\"GuvenlikNoktası1\":\"INSAAT\",\"KartNo\":\"000000803567858\",\"Sira\": 2},{\"Id\": 3,\"GuvenlikNoktası1\":\"ÇALISMA\",\"KartNo\":\"000003417926233\",\"Sira\": 3},{\"Id\": 4,\"GuvenlikNoktası1\":\"GÜVENLIK\",\"KartNo\":\"000001888909897\",\"Sira\": 4}]}}";
AddIstasyon(json);
}
public static void AddIstasyon(string json_string)
{
dynamic jsonObject = JObject.Parse(json_string);
string jsonToDeserializeStrongType = jsonObject["GuvenlikNoktaArray"]["GuvenlikNoktası"].ToString();
List<GuvenlikNoktası> result = JsonConvert.DeserializeObject<List<GuvenlikNoktası>>(jsonToDeserializeStrongType); ;
}
}
public partial class GuvenlikNoktası
{
public GuvenlikNoktası()
{
this.GüvenlikNoktasıOlay = new HashSet<GüvenlikNoktasıOlay>();
this.PanikButonuAlarmlari = new HashSet<PanikButonuAlarmlari>();
}
public int Id { get; set; }
public string GuvenlikNoktası1 { get; set; }
public string KartNo { get; set; }
public string Sira { get; set; }
public virtual ICollection<GüvenlikNoktasıOlay> GüvenlikNoktasıOlay { get; set; }
public virtual ICollection<PanikButonuAlarmlari> PanikButonuAlarmlari { get; set; }
}
public class GüvenlikNoktasıOlay
{
}
public class PanikButonuAlarmlari
{
}
}
Hope this helps
Your JSON data and your class definition do not fit together. Therefore the default values (NULL) are provided by the serializer.
In order to deserialize the given JSON data you need a class structure like:
public class Root
{
public LevelOne GuvenlikNoktaArray {get; set;}
}
public class LevelOne {
public IEnumerable<GuvenlikNoktası> GuvenlikNoktası {get; set;}
}
You can use this class.
public class GuvenlikNoktası
{
public int Id { get; set; }
public string GuvenlikNoktası1 { get; set; }
public string KartNo { get; set; }
public int Sira { get; set; }
}
public class GuvenlikNoktaArray
{
public IList<GuvenlikNoktası> GuvenlikNoktası { get; set; }
}
public class Example
{
public GuvenlikNoktaArray GuvenlikNoktaArray { get; set; }
}
You can use this link For your referencehttp://jsonutils.com/.

Categories

Resources