From the api call:
var httpClient = new HttpClient();
var uri = "https://api.postcodes.io/postcodes/";
var response = await httpClient.PostAsync(uri, data);
string result = response.Content.ReadAsStringAsync().Result;
var list = JsonConvert.DeserializeObject<GeoDataList>(result);
with two custom classes:
[Serializable]
public class GeoData
{
[JsonProperty("postcode")]
public string postcode { get; set; }
[JsonProperty("longitude")]
public string longitude { get; set; }
[JsonProperty("latitude")]
public string latitude { get; set; }
}
public class GeoDataList
{
[JsonProperty("result")]
public List<GeoData> geoDatas { get; set; }
}
The result contains this json-string:
{
"status": 200,
"result": [{
"query": "OX49 5NU",
"result": {
"postcode": "OX49 5NU",
"longitude": -1.069876,
"latitude": 51.6562
}
}, {
"query": "M32 0JG",
"result": {
"postcode": "M32 0JG",
"longitude": -2.302836,
"latitude": 53.455654
}
}, {
"query": "NE30 1DP",
"result": {
"postcode": "NE30 1DP",
"longitude": -1.439269,
"latitude": 55.011303,
}
}]
}
The list contains 3 empty objects. postcode, longitude, and latitude are null. How do I populate the inner objects (GeoData)?
Kind regard /Rudy
CodePudding user response:
So, when we have to work with JSON and we really don't want to grunt all this out by hand, because it's tedious and liable to error, we go to http://quicktype.io (or json2csharp, or some similar site) and we paste our JSON in there..
We fix up any syntax errors in the json (quicktype shows a red bar in the json-paste window), like the trailing comma on the last result latitude, and we get this bunch of classes generated by QuickType:
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using SomeNamespace;
//
// var root = Root.FromJson(jsonString);
namespace SomeNamespace
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class Root
{
[JsonProperty("status")]
public long Status { get; set; }
[JsonProperty("result")]
public ResultElement[] Result { get; set; }
}
public partial class ResultElement
{
[JsonProperty("query")]
public string Query { get; set; }
[JsonProperty("result")]
public ResultResult Result { get; set; }
}
public partial class ResultResult
{
[JsonProperty("postcode")]
public string Postcode { get; set; }
[JsonProperty("longitude")]
public double Longitude { get; set; }
[JsonProperty("latitude")]
public double Latitude { get; set; }
}
public partial class Root
{
public static Root FromJson(string json) => JsonConvert.DeserializeObject<Root>(json, SomeNamespace.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this Root self) => JsonConvert.SerializeObject(self, SomeNamespace.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
And the comment at the top tells us how to use it:
var root = Root.FromJson(jsonString);
And then if you just want the inner result objects you could:
root.Result.Select(r => r.Result).ToList()
If you don't like the class names that QT has picked, you can refactor/rename them in VS - the json will remain parsable because it also added all the [Jsonproeprty]
attributes for you with the names as per the JSON so the C# props can be anything you like
QT is Newtonsoft oriented; if you want to use the generated classes with System.Text.Json
you just have to adjust the attribute names with find/replace and a couple of other bits of tidy up
I have zero affiliation with QT