I've simplified the code (below) but I cannot figure out why the Result.Data property is not getting filled; it is always null. I've used jsonlint.com to validate the JSON (both this small sample and the full content). I built a separate project (using How to Deserialize a Complex JSON Object in C# .NET) and it successfully serializes the complex object listed there. But I cannot get this one to work and I'm stumped.
using System.Text.Json;
namespace JsonTest2;
public class Result
{
public string? Total { get; set; }
public string? Limit { get; set; }
public string? Start { get; set; }
protected List<Park>? Data { get; set; }
}
public class Park
{
public string? Id { get; set; }
}
internal class Program
{
var basepath = AppDomain.CurrentDomain.BaseDirectory;
var filepath = basepath.Split("\\bin")[0];
var filename = #$"{filepath}\NPS_response_small.json";
var jsonstr = File.ReadAllText(filename);
var response = JsonSerializer.Deserialize<Result>(jsonstr, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
}
This is the content of "NPS_response_small.json":
{
"total": "468",
"limit": "50",
"start": "0",
"data": [
{
"id": "77E0D7F0-1942-494A-ACE2-9004D2BDC59E"
},
{
"id": "6DA17C86-088E-4B4D-B862-7C1BD5CF236B"
},
{
"id": "E4C7784E-66A0-4D44-87D0-3E072F5FEF43"
}
]
}
you have to chanbe a protected attribute of property Data to a public. Json deserializer doesnt have any acces to this property
public List<Park>? Data { get; set; }
it would be much easier to use Newtonsoft.Json, but if you need protected for some reason, you can try this ( but I am not sure that it is a full replacement)
public List<Park>? Data { protected get; init ; }
[System.Text.Json.Serialization.JsonConstructor]
public Result (List<Park>? Data, string? Total, string? Limit, string? Start)
{
this.Data=Data;
this.Total=Total;
this.Limit=Limit;
this.Start=Start;
}
The API I am working on requires a very complicated JSON object be passed in as a string, along with other values. So I created a class like this:
public class BURequest
{
public Guid ID { get; set; }
public string JSONStr { get; set; } --->JSON passed in as string
public string VersionName { get; set; }
}
The API controller has the following method:
public async Task<IActionResult> Check ([FromBody] BURequest testRequest)
However I kept getting "After parsing a value an unexpected character was encountered: c. Path 'BURequest', line 4, position 3."
Here is the JSON string:
{
"content_version": "1",
"date_created": "2020-10-06T13:52:15.288Z",
"date_updated": "2020-10-06T13:54:24.325Z",
"tools": {
"car": true,
"truck": true
}
}
Is there any way to get around this problem without having to create a class for the JSON object itself? It's a complicated object and has a huge number of properties. Thanks!
p.s.I've verified that the JSON string is valid using JSONLint as suggested below.
I would use JsonElement for this:
public class BURequest
{
public Guid ID { get; set; }
public JsonElement JSONStr { get; set; } --->JSON passed in as string
public string VersionName { get; set; }
}
And then just get the value:
testRequest.JSONStr.ToString()
The Json needs to be:
{
"JSONStr" : {
"content_version": "1",
"date_created": "2020-10-06T13:52:15.288Z",
"date_updated": "2020-10-06T13:54:24.325Z",
"tools": {
"car": true,
"truck": true
}
}
}
Just adding an answer to go with the comment on the question. Changing the type of the JSONStr property from string to JObject solves the problem.
so I have a problem:
The code in JSON that you see there is a response that a webpage gives me. And the thing I want to do is really simple:
I just want to parse for example the "user_id", or "class".
I tried few things on stackoverflow that I found but no one works...
{
"data": {
"user": {
"class": "user",
"user_id": "81046537",
"etp_guid": "76411082-73ab-5aaa-9242-0bb752cf97a4",
},
},
}
Thanks !
There are many ways you can extract the user_id from the json. The most common way is to use Newtonsoft.Json package.
Assuming the json is stored as a string, you can call JObject.Parse().
var data = "{'data': {'user': {'class': 'user','user_id': '81046537','etp_guid': '76411082-73ab-5aaa-9242-0bb752cf97a4'} } }";
JObject jObject = JObject.Parse(data);
var userId = jObject["data"]["user"]["user_id"];
Console.WriteLine($"User id {userId}");
If your json is stored as a n object, then call JObject jObject = new JObject(data)
A preferred way is to serialise your json using business object. Simply create classes to match the json structure. e.g:
public class Response
{
public Data Data { get; set; }
}
public class Data
{
public User User { get; set; }
}
public class User
{
public string Class { get; set; }
public string User_id { get; set; }
public string Etp_guid { get; set; }
}
Then deserialize your object. e.g:
var response = JsonConvert.DeserializeObject<Response>(data);
Console.WriteLine($"User id {response.Data.User.User_id}");
I am new to Json and trying to do some examples with it. I have Json data like this:
{
"Title": "The Avengers",
"Year": "2012",
"Rated": "PG-13",
"Released": "04 May 2012",
"Runtime": "143 min",
"Genre": "Action, Adventure, Sci-Fi",
"Director": "Joss Whedon",
"Writer": "Joss Whedon (screenplay), Zak Penn (story), Joss Whedon (story)",
"Actors": "Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth",
"Plot": "Earth's mightiest heroes must come together and learn to fight as a team if they are going to stop the mischievous Loki and his alien army from enslaving humanity.",
"Language": "English, Russian, Hindi",
"Country": "USA",
"Awards": "Nominated for 1 Oscar. Another 38 wins & 79 nominations.",
"Poster": "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "8.0/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "92%"
},
{
"Source": "Metacritic",
"Value": "69/100"
}
],
"Metascore": "69",
"imdbRating": "8.0",
"imdbVotes": "1,200,683",
"imdbID": "tt0848228",
"Type": "movie",
"DVD": "25 Sep 2012",
"BoxOffice": "$623,279,547",
"Production": "Walt Disney Pictures",
"Website": "http://marvel.com/avengers_movie",
"Response": "True"
}
I can get the data and read it just fine but when it comes deserialize I get the following error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Deneme.Modeller.Main]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
This is my code
string url = "http://www.omdbapi.com/?apikey=7663ce8e&t=Avengers";
WebRequest request = WebRequest.Create(url);
WebResponse reply;
reply = request.GetResponse();
StreamReader returninfo = new StreamReader(reply.GetResponseStream());
string getinfo = returninfo.ReadToEnd();
List<Main> Info = JsonConvert.DeserializeObject<List<Main>>(getinfo);
and for models this is first main:
public string Title { get; set; }
public string Year { get; set; }
public string Rated { get; set; }
public string Released { get; set; }
public string Runtime { get; set; }
public string Genre { get; set; }
public string Director { get; set; }
public string Writer { get; set; }
public string Actors { get; set; }
public string Plot { get; set; }
public string Language { get; set; }
public string Country { get; set; }
public string Awards { get; set; }
public string Poster { get; set; }
public List<Rating> Ratings { get; set; }
public string Metascore { get; set; }
public string imdbRating { get; set; }
public string imdbVotes { get; set; }
public string imdbID { get; set; }
public string Type { get; set; }
public string DVD { get; set; }
public string BoxOffice { get; set; }
public string Production { get; set; }
public string Website { get; set; }
public string Response { get; set; }
second one is for Ratings:
public string Source { get; set; }
public string Value { get; set; }
public virtual ICollection<Main> Mains { get; set; }
It's about Json array, but I looked asked questions about this problem and tried to fix it but no luck. What am I missing?
You are trying to deserialize a single object of type Main into a list of objects.
You can either change your code to deserialize into a single object instead of a list or you can alter your JSON to represent an array of objects.
The first option would be
Main Info = JsonConvert.DeserializeObject<Main>(getinfo);
And the second option
[{"Title":"The Avengers","Year":"2012","Rated":"PG-13","Released":"04 May 2012","Runtime":"143 min","Genre":"Action, Adventure, Sci-Fi","Director":"Joss Whedon","Writer":"Joss Whedon (screenplay), Zak Penn (story), Joss Whedon (story)","Actors":"Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth","Plot":"Earth's mightiest heroes must come together and learn to fight as a team if they are going to stop the mischievous Loki and his alien army from enslaving humanity.","Language":"English, Russian, Hindi","Country":"USA","Awards":"Nominated for 1 Oscar. Another 38 wins & 79 nominations.","Poster":"https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg","Ratings":[{"Source":"Internet Movie Database","Value":"8.0/10"},{"Source":"Rotten Tomatoes","Value":"92%"},{"Source":"Metacritic","Value":"69/100"}],"Metascore":"69","imdbRating":"8.0","imdbVotes":"1,200,683","imdbID":"tt0848228","Type":"movie","DVD":"25 Sep 2012","BoxOffice":"$623,279,547","Production":"Walt Disney Pictures","Website":"http://marvel.com/avengers_movie","Response":"True"}]
(simply add brackets)
Which option you have to choose is depending on your requirements, i.e. if you want to allow multiple objects or just one.
Main Info = JsonConvert.DeserializeObject<Main>(getinfo);
Your json string has only one Main object, you were trying to get a List
You try to deserialize one JSON object into a list of objects.
This is an example of simple object:
{ "field": 123 }
To deserialize it you need to:
var obj = JsonConvert.DeserializeObject<SomeModel>(json);
But if you have an array of objects:
[{ "field": 123 }, { "field": 123 }]
You will be able to deserialize them to a list like this:
var objs = JsonConvert.DeserializeObject<SomeModel[]>(json);
or
var objs = JsonConvert.DeserializeObject<List<SomeModel>>(json);
Solutions to your question:
Change deserialization type to a single object.
Wrap your JSON around with []
when we call api 'http://www.omdbapi.com/?apikey=7663ce8e&t=Avenger' we gets an objet not an array of object
try
var info = JsonConvert.DeserializeObject<Main>(getinfo);
If you want list of movies try a other api b.e.: themoviedbAPI
I am able to get a JSON object with a list of surveys having a set of attributes for each of them. I have a class defined for surveys where I am defining all the survey attributes based on the obtained JSON object. I am facing an error while defining question.id attribute. Please suggest me the best way to solve this problem.
JSON Data:
"surveys":
{
"id": 20128672,
"trueFalse": false,
"question": "Any accidents on site today?",
"question.id": 1097329,
"question.tag": 0,
"images": [],
"videos": []
},
Survey class:
public class survey
{
public string id { get; set; }
public Nullable<bool> trueFalse { get; set; }
public string question { get; set; }
public string question.id { get; set; } //error in writing the question id attribute
public string desc { get; set; }
//public bool trueFalse { get; set; }
public string FormattedAnswer
{
get
{
if (trueFalse == null) return "NA";
return trueFalse == true ? "YES" : "NO";
}
}
}
I'm not sure what json lib you're using here but assuming it's json.net you can resolve this with a simple annotation mapping the json fields name to the C# property, the name you're giving that property in C# is not valid which is why you're getting the error, no periods in field names.
[JsonProperty("question.id")]
public int id { get; set; }
Also, I modified your type because it was wrong too, the json value is an int, not a string. If you're not using json.net, I'm sure you'll find similar features in the lib you are using, google json annotation or something along those lines with the packages name to find appropriate docs.