Deserialize json array in Xamarin [duplicate] - c#

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
]
]
]
]

Related

How to deserialize a json array with multiple data types?

I now need to deserialize a JSON that looks like this:
{
"arguments": {
"game": [
"--username",
"--version",
"--assetsDir",
{
"rules": [
{
"action": "allow",
"features": {
"is_demo_user": true
}
}
],
"value": "--demo"
},
{
"rules": [
{
"action": "allow",
"features": {
"has_custom_resolution": true
}
}
],
"value": [
"--width",
"--height"
]
}
]
}
}
As you can see, the array named "game" has both "value" and "object" in it. (But the fact is WORSE than this example, the number of elements is NOT certain)
And the data type of arguments.game[*].value is NOT certain, too.
I used to use classes to describe it, but deserialization failed.
Can't seem to describe an array with multiple element types with a class?
I am using Json.NET. Is there any way to deserialize this "game" array.
Thanks.
Is it a requirement to deserialize to an instance of a class? You could use an ExpandoObject:
using System.Dynamic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
Console.WriteLine("Hello, World!");
string json = #"{
""arguments"": {
""game"": [
""--username"",
""--version"",
""--assetsDir"",
{
""rules"": [
{
""action"": ""allow"",
""features"": {
""is_demo_user"": true
}
}
],
""value"": ""--demo""
},
{
""rules"": [
{
""action"": ""allow"",
""features"": {
""has_custom_resolution"": true
}
}
],
""value"": [
""--width"",
""--height""
]
}
]
}
}";
var expConverter = new ExpandoObjectConverter();
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json, expConverter);
The obj variable will contain the result of the JSON conversion, then you can traverse the dynamic object in code.
For example, to get a list of strings under 'game':
IList<object> list = new List<object>(obj.arguments.game);
foreach (object str in list)
{
if (str as string != null)
{
Console.WriteLine(str as string);
}
}

Cannot deserialize json object into array

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"
}
]

How do I make JSON accessible from inside of many arrays?

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
}

How to write the value of one json property in one line?

It is necessary to write value of "Coordinates" property in json without hyphenation for the following lines, not using ToString() (without converting the value to a string). The desired result is shown below.
{
"Id": null,
"Style": "1234",
"Geometry": {
"Type": "Polygon",
"Coordinates": [[[47541.470259278358,6846.8710054924586],[47540.359922950891,6845.4552435801925],[47541.470259278358,6846.8710054924586]]],
"Properties": [
{
"PointType": "Straight"
},
{
"PointType": "Straight"
},
{
"PointType": "Straight"
}
]
}
}
but not:
{
"Id": null,
"Style": "1234",
"Geometry": {
"Type": "Polygon",
"Coordinates": "[[[47541.470259278358,6846.8710054924586],[47540.359922950891,6845.4552435801925],[47541.470259278358,6846.8710054924586]]]",
"Properties": [
{
"PointType": "Straight"
},
{
"PointType": "Straight"
},
{
"PointType": "Straight"
}
]
}
}
A function that serializes the corresponding class object in json:
JToken ToJson()
{
using (var writer = new JTokenWriter()) {
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, this);
return writer.Token;
}
}
it seems your second case contains Coordinates property as serialized string.
why should not use
var string = JsonConvert.SerializeObject(YourObject) ?
But you should install https://www.nuget.org/packages/Newtonsoft.Json/ first
You could use string type for properties where you need double quotes and use array or number if you don't need it

JSON Get List of attributes values

I have the following JSON, and I want to take a list of IDs with its values
For example in LINQ something like this: result.Select(x=>x.id)
I tried this:
var inner = outer["pictures"].Value<JArray>().ToList();
I have a list there but with all attributes but I am not able to select just IDs since it is an anonymous list.
outer
{{
"id": "669654603",
"pictures": [
{
"id": "659745-MLA25600661898_052017",
"url": "http://mla-s2-p.mlstatic.com/659745-MLA25600661898_052017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/659745-MLA25600661898_052017-O.jpg",
"size": "500x365",
"max_size": "625x457",
"quality": ""
},
{
"id": "908422-MLA25658267858_062017",
"url": "http://mla-s2-p.mlstatic.com/908422-MLA25658267858_062017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/908422-MLA25658267858_062017-O.jpg",
"size": "47x47",
"max_size": "47x47",
"quality": ""
},
{
"id": "794138-MLA25658267889_062017",
"url": "http://mla-s2-p.mlstatic.com/794138-MLA25658267889_062017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/794138-MLA25658267889_062017-O.jpg",
"size": "40x40",
"max_size": "40x40",
"quality": ""
}
]
}}
When working with Newtonsoft JSON you can do it like this:
var values = JObject.Parse(jsonString)["pictures"].Select(p => p["id"].Value<string>()).ToList();
In order to be valid your json should not contain double curly brackets:
{
"id": "669654603",
"pictures": [ ... ]
}
You can parse it without additional classes:
var ids = JObject.Parse(json)["pictures"].Select(p => (string)p["id"]);
Output:
[
"659745-MLA25600661898_052017",
"908422-MLA25658267858_062017",
"794138-MLA25658267889_062017"
]
Or you can create several classes to hold your json data:
public class Container
{
public List<Picture> Pictures { get; set; }
}
public class Picture
{
public string Id { get; set; }
// you can add other properties here
}
And use strongly-typed parsing:
var ids = JsonConvert.DeserializeObject<Container>(json).Pictures.Select(p => p.Id);

Categories

Resources