3

I am writing a method that takes a British post code and returns the Latitude and Longitude of this postcode as a "Location" object.

public class Location
{
    public double Longitude;
    public double Latitude;
}

I am using the API from https://postcodes.io/ that takes a postcode and returns a fairly large set of data about it. For example (Buckingham Palace if you're interested):

{
"status": 200,
"result": {
    "postcode": "SW1A 1AA",
    "quality": 1,
    "eastings": 529090,
    "northings": 179645,
    "country": "England",
    "nhs_ha": "London",
    "longitude": -0.141587597876975,
    "latitude": 51.5010091564599,
    "european_electoral_region": "London",
    "primary_care_trust": "Westminster",
    "region": "London",
    "lsoa": "Westminster 018C",
    "msoa": "Westminster 018",
    "incode": "1AA",
    "outcode": "SW1A",
    "parliamentary_constituency": "Cities of London and Westminster",
    "admin_district": "Westminster",
    "parish": "Westminster, unparished area",
    "admin_county": null,
    "admin_ward": "St James's",
    "ccg": "NHS Central London (Westminster)",
    "nuts": "Westminster",
    "codes": {
        "admin_district": "E09000033",
        "admin_county": "E99999999",
        "admin_ward": "E05000644",
        "parish": "E43000236",
        "parliamentary_constituency": "E14000639",
        "ccg": "E38000031",
        "nuts": "UKI32"
        }
    }
}

Currently I have set it up to get the data by generating classes for the data using Visual Studio's "Paste Special > Paste JSON as Classes" functionality and then using JSON.Net to Deserialize the whole set of data and then use the latitude and longitude from the resulting object to create a new Location object.

Rootobject locationData = JsonConvert.DeserializeObject<Rootobject>(content);

        Location locationToReturn = new Location()
        {
            Latitude = locationData.result.latitude,
            Longitude = locationData.result.longitude
        };

It seems silly to me that I have to go through the effort of Deserializing the whole thing when I only want two of the fields.

So the question is:

Can I deserialize only the latitude and longitude fields?

More specifically to my example, can I deserialize the latitude and longitude fields directly into a new instance of my Location class?

Tom Clifford
  • 75
  • 2
  • 7
  • 1
    I apologise if this has already been answered, but I couldn't find anything that I thought matched my situation exactly. – Tom Clifford Jan 17 '18 at 15:44
  • 1
    Look into the desirialization into a Dynamic object. You then could use it like this. – Dieter B Jan 17 '18 at 15:45
  • Are you concerned about performance? I haven't tested this, but I'm pretty sure the additional overhead of deserializing 20 fields isn't much more than deserializing 2 fields. – Nate Barbettini Jan 17 '18 at 15:51
  • 1
    First of all, let's clarify a bit terms that we use. Newtonsoft.js deserializes object. The deserialization of json with Newtonsoft is a process of converting some string into JObject class. After that it tries to map this JObject to your custom type. So one way is to use JObject directly and access its properties dynamically, but keep in mind that first it will deserialize the whole json so performance gain would be minimal if any... – Fabjan Jan 17 '18 at 15:57
  • @Fabjan Thanks, that helps me understand it a bit better. I was more just looking at a way of reducing unecesarry code than any performance gain. – Tom Clifford Jan 17 '18 at 16:13

4 Answers4

2

You can load your data into a dynamic object. And then read it from there.

        dynamic locationData = JsonConvert.DeserializeObject<dynamic>(content);

        Location locationToReturn = new Location()
        {
            Latitude = locationData.result.latitude,
            Longitude = locationData.result.longitude
        };

        Console.WriteLine("Latitude: " + locationToReturn.Latitude);
        Console.WriteLine("Longitude: " + locationToReturn.Longitude);

        Console.ReadLine();

This way you can get other columns or values as well w/o enumerating through all the fields.

Dieter B
  • 1,142
  • 11
  • 20
  • I'm not fond of dynamic object type for a number of reasons. But this suggestion just changed my mind about a good use case! Thank you. – tatmanblue Jan 17 '18 at 16:17
2

You could do what you want using a JObject like this:

Location locationData = JObject.Parse(content)["result"].ToObject<Location>();

Fiddle: https://dotnetfiddle.net/vWwLUf


Alternatively just change the class definition for your Rootobject class:

class Rootobject
{
    [JsonProperty("result")]
    public Location Location { get; set; }
}

Then you can do this:

Location locationData = JsonConvert.DeserializeObject<Rootobject>(content).Location;

Fiddle: https://dotnetfiddle.net/imng8Q

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
1

Microsoft recommend to use System.Text.Json for security and performance reason.

// jsonDocument must be disposed, because it utilizes resources from pooled memory
using (JsonDocument jsonDocument = JsonDocument.Parse(jsonString))
{                
    JsonElement rootElement = jsonDocument.RootElement;
    JsonElement jsonElement = rootElement.GetProperty("EmployeeName");
    string employeeName = jsonElement.ToString();
}
Wizard
  • 121
  • 3
  • 5
0

You can use Newtonsoft.Json (Json.Net) to walk through the json object yourself and only grab the values you need.

You would want to use a JObject to capture the whole result. Go to the child token of result, then grab the child items for longitude and latitude and deserialize as needed.

You can check out this answer as well How do I enumerate through a JObject?

Matti Price
  • 3,351
  • 15
  • 28