I have this data structure:
public class AutoCompleteObject
{
public Predictions[] predictions { get; set; }
public string status { get; set; }
}
public class Predictions
{
public string description { get; set; }
}
and this is the result of my api:
{
"predictions": [
{
"description": "Hoisberg 142, Hamburg, Germany",
"matched_substrings": [
{
"length": 8,
"offset": 0
},
{
"length": 2,
"offset": 9
},
{
"length": 7,
"offset": 13
}
],
"place_id": "ChIJr_7fvYSKsUcRejFkuj1Nr0o",
"reference": "ChIJr_7fvYSKsUcRejFkuj1Nr0o",
"structured_formatting": {
"main_text": "Hoisberg 143",
"main_text_matched_substrings": [
{
"length": 8,
"offset": 0
},
{
"length": 2,
"offset": 9
}
],
"secondary_text": "Hamburg, Germany",
"secondary_text_matched_substrings": [
{
"length": 7,
"offset": 0
}
]
},
}
],
"status": "OK"
}
I am trying to deserialize into my object using this:
ObservableCollection<AutoCompleteObject> res = JsonConvert.DeserializeObject<ObservableCollection<AutoCompleteObject>>(content);
But it fails stating it was unable to put the string into the array. But the result is an array and can contain many elements. What am I missing?
The exception thrown is the following
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.ObjectModel.ObservableCollection`1[AutoCompleteObject]' 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.
So the exception point to the problem being that it expects an array. If you look at the json example you provided it starts with { which means it's a json object. To fix it you need to wrap the json object in [] or deserialize to a different class.
For example your json would have to look like this:
[
{
"predictions": [
{
"description": "Hoisberg 142, Hamburg, Germany",
"matched_substrings": [
{
"length": 8,
"offset": 0
},
{
"length": 2,
"offset": 9
},
{
"length": 7,
"offset": 13
}
],
"place_id": "ChIJr_7fvYSKsUcRejFkuj1Nr0o",
"reference": "ChIJr_7fvYSKsUcRejFkuj1Nr0o",
"structured_formatting": {
"main_text": "Hoisberg 143",
"main_text_matched_substrings": [
{
"length": 8,
"offset": 0
},
{
"length": 2,
"offset": 9
}
],
"secondary_text": "Hamburg, Germany",
"secondary_text_matched_substrings": [
{
"length": 7,
"offset": 0
}
]
}
}
],
"status": "OK"
}
]
Related
I want to serialize an object using json.net and c#. For that i have created a custom contract resolver that extends DefaultContractResolver class and also i have override the CreateProperties method. My class is something like
public class Hierarchy{
[JsonProperty("id")]
public int Id{get;set;}
[JsonProperty("parentId")]
public int ParentId{get;set;}
[JsonProperty("nodes")]
public List<Hierarchy> Nodes{get;set;}
}
Now i have an object of this class
{
"id": 3585,
"parentId": 0,
"nodes": [
{
"id": 3586,
"parentId": 3585,
"nodes": [
{
"id": 3587,
"parentId": 3586,
"nodes": null
}
]
},
{
"id": 3599,
"parentId": 3585,
"nodes": [
{
"id": 3600,
"parentId": 3599,
"nodes": null
},
{
"id": 3601,
"parentId": 3599,
"nodes": null
},
{
"id": 3602,
"parentId": 3599,
"nodes": null
},
{
"id": 3603,
"parentId": 3599,
"nodes": null
}
]
},
{
"id": 3744,
"parentId": 3585,
"nodes": null
}
]
}
Now my CustomDefaultResolver class is something like
public class CustomRetrieveResponseResolver : DefaultContractResolver
{
private readonly IList<string> _propertiesToInclude;
public CustomRetrieveResponseResolver(IList<string> propertiesToInclude , Type objType)
{
_propertiesToInclude = propertiesToInclude;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
// some code here
}
}
I'm passing a list of strings to the constructor which has the name of the properties I want to include in the final object. For example if propertiesToInclude = { "id" } i will get output
{ "id" : 3585 }
Also when propertiesToInclude = { "id" , "nodes" } i will get the entire object. I know that json.net will bind some contract with Type of object so all the Hierarchy type object will be serializing in the same manner.
So When propertiesToInclude = { "nodes.id" } is something like this i want an output
{
"nodes" : [
{
"id": 3586
},
{
"id": 3599
},
{
"id": 3744
}
]
}
But I'm getting
{
"nodes" : [
{
"nodes":null
},
{
"nodes":null
},
{
"nodes": null
}
]
}
This means I want to serialize the outer Hierarchy type and the inner Hierarchy type in a different way. I know that CreateProperties will be going to call only once and that time it will bind some contract or way of serializing Hierarchy Type object and it will use the same contract for every Hierarchy Type object independent of its position in the object.
So is there any way of defining different contracts ( or way of serializing) for the same Type occurring at different hierarchies in the same object?
This question already has answers here:
How to auto-generate a C# class file from a JSON string [closed]
(3 answers)
Closed 1 year ago.
I want to Deserialise this json file in my Xamarin android App to only get the coordinates.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "6849033",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
6.562265,
40.36426
],
[
6.5622743,
40.3642745
],
[
6.5622944,
40.3642897
],etc...
Here is my approach with my class
public class Cadastre
{
public List<List<List<List<float>>>> coordinates { get; set; }
public Cadastre()
{
}
}
And finally here my code to Deserialize my json file
string responseFinished = await GetJson();
Cadastre c = JsonConvert.DeserializeObject<Cadastre>(responseFinished);
I tried many solutions but my coordinates are still null.
If anyone has a solution or a lead I would be grateful.
try this
var jsonObject=JObject.Parse(json);
var coordinates = ((JArray)jsonObject["features"][0]["geometry"]["coordinates"][0][0]).Select(c => new { One = c[0], Two = c[1]}).ToList();
result
[
{
"One": 6.562265,
"Two": 40.36426
},
{
"One": 6.5622743,
"Two": 40.3642745
},
{
"One": 6.5622944,
"Two": 40.3642897
}
]
or if you want to deserialize your way
List<List<List<List<float>>>> coordinates = ((JArray)jsonObject["features"][0]["geometry"]["coordinates"]).ToObject<List<List<List<List<float>>>>>();
result
[
[
[
[
6.562265,
40.36426
],
[
6.5622745,
40.364273
],
[
6.5622945,
40.36429
]
]
]
]
I hope it doesn't seem like I want to be spoon-fed at this rate of asking questions, but this next question is a bit more difficult and I don't understand how to solve this at all.
{
"results": [
{
"id": "5d914028302b840050acbe62",
"picture": "https://utellyassets9-1.imgix.net/api/Images/4e4d50a0040fd4500193202edbafce6a/Redirect",
"name": "BoJack Horseman",
"locations": [
{
"icon": "https://utellyassets7.imgix.net/locations_icons/utelly/black_new/NetflixIVAUS.png?w=92&auto=compress&app_version=ae3576e2-0796-4eda-b953-80cadc8e2619_eww2020-05-08",
"display_name": "Netflix",
"name": "NetflixIVAUS",
"id": "5d81fe2fd51bef0f42268f0f",
"url": "https://www.netflix.com/title/70298933"
}
],
"provider": "iva",
"weight": 5654,
"external_ids": {
"iva_rating": null,
"imdb": {
"url": "https://www.imdb.com/title/tt3398228",
"id": "tt3398228"
},
"tmdb": {
"url": "https://www.themoviedb.org/movie/61222",
"id": "61222"
},
"wiki_data": {
"url": "https://www.wikidata.org/wiki/Q17733404",
"id": "Q17733404"
},
"iva": {
"id": "783721"
},
"gracenote": null,
"rotten_tomatoes": null,
"facebook": null
}
},
{
"id": "5e2ce07890c0e033a487e3d2",
"picture": "https://utellyassets9-1.imgix.net/api/Images/326d2853ff6885c41b9adb05278017f6/Redirect",
"name": "Dragon Ball Z: Bojack Unbound",
"locations": [
{
"icon": "https://utellyassets7.imgix.net/locations_icons/utelly/black_new/iTunesIVAUS.png?w=92&auto=compress&app_version=ae3576e2-0796-4eda-b953-80cadc8e2619_eww2020-05-08",
"display_name": "iTunes",
"name": "iTunesIVAUS",
"id": "5d80a9a5d51bef861d3740d3",
"url": "https://itunes.apple.com/us/movie/dragon-ball-z-bojack-unbound-subtitled-original-version/id1381102560"
}
],
"provider": "iva",
"weight": 0,
"external_ids": {
"iva_rating": null,
"imdb": {
"url": "https://www.imdb.com/title/tt0142238",
"id": "tt0142238"
},
"tmdb": {
"url": "https://www.themoviedb.org/movie/39105",
"id": "39105"
},
"wiki_data": {
"url": "https://www.wikidata.org/wiki/Q1255010",
"id": "Q1255010"
},
"iva": {
"id": "406043"
},
"gracenote": null,
"rotten_tomatoes": null,
"facebook": null
}
}
],
"updated": "2020-05-08T05:19:01+0100",
"term": "Bojack",
"status_code": 200,
"variant": "ivafull"
}
Alright, so the first 0: represents the option that the API returned (so in this case it's bojack horseman) and any following number (if it said 1: afterward) would be a different result.
I tried writing a second class to deal with results (resultoverall) that is controlled by the overall,
public class overall
{
[JsonProperty("status_code")]
public string status_code { get; set; }
[JsonProperty("term")]
public string term { get; set; }
[JsonProperty("updated")]
public string updated { get; set; }
[JsonProperty("results")]
public List<resultoverall> results { get; set; }
}
public partial class resultoverall
{
[JsonProperty("name")]
public string name { get; set; }
}
and tried
overall BestGamer = JsonConvert.DeserializeObject<overall>(thicky);
List<overall> ObjOrderList = JsonConvert.DeserializeObject<List<overall>>(thicky);
to be able to access data from both outside of the 0: and inside of the 0: (BestGamer / overall handles outside, resultoverall / Tapioca handles inside, but I get error about the type requiring a JSON array
even though it is already in an array format.
How do I set this up to access data inside of the 0:, for each number that appears (so if there is 2 options I can access info from both?
Using Console.WriteLine(BestGamer.updated); correctly gives me the info from the overall group, but using the Console.WriteLine(BestGamer.results.name); does not work, saying:
Error CS1061 'extension method 'name' accepting a first argument of type 'List<resultoverall>' could be found (are you missing a using directive or an assembly reference?)
You have a JSON object, not an array. Therefore you can't deserialize it as an array. That is correct. You are already deserializing it to an object. So after
overall BestGamer = JsonConvert.DeserializeObject<overall>(thicky);
You can access the objects in results like
var numberOfResults = BestGamer.results.Count;
var firstResult = BestGamer.results[0];
var firstResultsName = BestGamer.results[0].name;
// or loop through the results
foreach (var item in BestGamer.results)
{
// item.Name gives you the name of the current result
}
I'm calling an API endpoint that return me a JSON some data and I need to deserialize it into classes and nested classes that may contains ReactiveProperty fields ( a type coming from UniRx library which is a reimplemntation of Reactive extensions for Unity3D ).
I'm new to C#, I tried some things, but I can't achieve it the way i want.
Here is the json returned by my Api ( in reality there are more data but this example will suffice ) :
"user": {
"id": "87f2ae6e-af99-4f8e-9d69-08de6ad6baf8",
"username": "test",
"email": "test#test.com",
"money": 800,
"morale": 100,
"health": 100,
"credits": 15,
"energy": 100,
"banned_at": null,
"last_connection": null,
"officers": [
{
"id": "2b72d9d4-635c-4b32-9575-5df49f566e93",
"name": "David Le Salmon",
"is_available": true,
"age": 42,
"condition": 100,
"user_id": "87f2ae6e-af99-4f8e-9d69-08de6ad6baf8"
},
{
"id": "ebc4074c-7b94-4ea3-96d9-f80608972afa",
"name": "Philippe Mercier",
"is_available": true,
"age": 34,
"condition": 100,
"user_id": "87f2ae6e-af99-4f8e-9d69-08de6ad6baf8"
},
{
"id": "edba67b5-9053-4fd6-b64e-6b85f4d0cc25",
"name": "Raymond Wagner-Berthelot",
"is_available": true,
"age": 55,
"condition": 100,
"user_id": "87f2ae6e-af99-4f8e-9d69-08de6ad6baf8"
}
],
"vehicles": [
{
"id": "3161d274-ed2a-491b-8515-beb7da9bfd29",
"mileage": 0,
"health": 100,
"level": 3,
"equipment_level": 4,
"vehicle_prefab_id": "14e8d96f-0e85-40ad-b01b-5f00a37b1108"
},
{
"id": "ff984c79-4511-4ade-92d1-9bf6899a243c",
"mileage": 0,
"health": 100,
"level": 4,
"equipment_level": 4,
"vehicle_prefab_id": "14e8d96f-0e85-40ad-b01b-5f00a37b1108"
}
]
}
}
I defined some classes like this :
[Serializable]
public class AppState {
public User user = new User();
}
[Serializable]
public class User {
public string username;
public string email;
public ReactiveProperty<int> money = new ReactiveProperty<int>();
public ReactiveProperty<int> morale = new ReactiveProperty<int>();
public ReactiveProperty<int> health = new ReactiveProperty<int>();
public ReactiveProperty<int> energy = new ReactiveProperty<int>();
public List<Officer> officers = new List<Officer[]>();
public List<Vehicles> vehicles = new List<Vehicle>();
}
Officer and Vehicle are defined in the same way, some fields are ReactiveProperty, some not.
And here how I tried to deserialize :
RestClient.Get("/getAppState").Then(response => {
var stuff = JsonConvert.DeserializeObject<AppState>(response.Text);
})
This code throws this error :
Could not cast or convert from System.String to UniRx.ReactiveProperty
I found something that "work", I assigned all ReactiveProperty fields manually, but it's really tedious.
Is there a way to do this in C#?
Make the Reactive property fields NonSerializable.
Make new serializable String fields.
Deserialize the JSON.
Add some functions to your class(es) that cast the string representations into your ReactiveProperty variables.
Call those functions after you desierialize your JSON.
Note: I am unfamiliar with ReactiveProperty, you'll need to investigate that library to find the best way of casting a string into those objects.
I have the following JSON array, that can also hold null values for some of the elements in the var array. The elements in the var array are always fix.
"vars": [
{
"varCol": [
{
"visible": false,
"val": 1,
},
{
"visible": false,
"val": 5,
},
{
"visible": false,
"val": 5,
},
null
],
"Type": "Type1"
"UniqueId": "ID1"
},
{
"varCol": [
{
"visible": true,
"val": 1,
},
null,
{
"visible": false,
"val": 5,
},
null
],
"Type": "Type2",
"UniqueId": "ID2"
}
]
I have the following C# deserializer classes:
public class Var
{
public int VarId { get; set; }
public string Type { get; set; }
public List<VarCol> VarCols { get; set; }
}
public class VarCol
{
public int VarColId { get; set; }
public bool Visible { get; set; }
public float Val { get; set; }
}
My desired output here is to have an entry in the VarCol that always holds the fixed structure of values in the array. In this case 4 entries in the varCol array for each vars element.
For the deserialization of the JSON I am using:
Var v = JToken.Parse(json_string).ToObject<Var>();
I wanted to insert this as a comment but it is too long so I have to post it as an answer.
Pay attention to commas because your JSON is not valid. I think you want to have something like this:
{
"vars": [
{
"varCol": [
{
"visible": false,
"val": 1
},
{
"visible": false,
"val": 5
},
{
"visible": false,
"val": 5
},
null
],
"Type": "Type1",
"UniqueId": "ID1"
},
{
"varCol": [
{
"visible": true,
"val": 1
},
null,
{
"visible": false,
"val": 5
},
null
],
"Type": "Type2",
"UniqueId": "ID2"
}
]
}
Have a nice day,
Alberto
Not sure what are you trying to achieve, because JToken.Parse() handles null values pretty much the same way as any other object value, so varCol will always have 4 elements.
Here's some test code: http://dotnetfiddle.net/9gGdH9
Sorry, my question was misleading.
The problem I was facing was saving to the DB through Entity Framework a null VarCol in the Var collection. I needed this to be able to know which of the elements in the collection is null, since I have a fixed size list.I solved this by instantiating the null VarCol with an empty VarCol as also Alex Skalozub indicated in one of his comments:
It depends on the way your object is stored in the database. If VarCol
has a many-to-one relation with Var, EF will probably store reference
to Var record in VarCol table. But null record cannot be saved to
database. That's why reading back will bring only those records that
were saved. You probably need to do some post-processing after parsing
JSON to replace null values with empty records before saving to DB. –
Alex Skalozub 5 hours ago