❔ How to get specific fields from a Http GET request
I am working with a test API for learning purposes, I am using the following snippet to actually return the request body:
I get a response such as:
How could I go about getting a specific field from this output, such as the "name" or "images"?
111 Replies
Typically you would deserialize that into an object that you control. Create a class that has properties that have the same names as the fields in the JSON and use either NewtonSoft or System.Text.Json to deserialze that into a class.
Another option is using something like JsonPath to query the fields that you need. https://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm
So if I just wanted an object that held the image and name would that be possible?
await client.GetAsJsonAsync<Model>(url)
Yep. You don't need to create a property for each field. Just the ones you need.
so this is the changes:
obviously no connection yet, you mentioned JSON etc, is there a best method to deserialize?
sorry if that doesn't make a lot of sense, i'm new to working with requests
Look at what ZZZZZZZZ posted
where would that fit into this code? and what should go into <Model> and (url)? the URL currently being used in the request is
Model
is the class you want to deserialize to
url
is the... urlI'd need to see a bit more, but instead of
var response = await client.SendAsync(request)
it's var response = await client.GetAsJsonAsync<ClothingAttributes>(your url here);
Assuming
client
is an HttpClient
of courseI can post the whole script, this is in a Unity project:
Ah oof ouch my bones Unity
First of all,
async void
is the devil
Second, you have an API key in this codeIn the end i want to be able to click a button for male or female and put an outfit on screen generated from this H&M API
Right, this is a free test website for messing with different APIs, this is a local hobby project for learning so is it bad to provide it here?
Someone can now make requests to this API on your behalf
Usually not the best thing to have happen
right, well i can generate a new one after this then, like i said i'm just using this for personal learning
Regardless, it seems you are using HttpClient so my code should work
Although... I think this extension method uses System.Text.Json
Which Unity doesn't support
So you might need to go oldschool after all
You'll need a lot more classes to get what you want, it's nested response.
$jsongen
Instantly parse JSON in any language | quicktype
Whether you're using C#, Swift, TypeScript, Go, C++ or other languages, quicktype generates models and helper code for quickly and safely reading JSON in your apps. Customize online with advanced options, or download a command-line tool.
Convert JSON to C# Classes Online - Json2CSharp Toolkit
Convert any JSON object to C# classes online. Json2CSharp is a free toolkit that will help you generate C# classes on the fly.
Yeah haha I don't know what most of this means, why can't I use this class I made and just create new ones for each clothing item?
The class has to match the JSON
Period
in the end i need 3 requests for 3 item types, and then need an image and their name
It can skip some properties, but the properties it has have to match
Period
ok, so then for this object :
are these names not correctly formatted?
For your json, I cleaned it up a bit and generated this:
public class Image
{
public string url { get; set; }
public string baseUrl { get; set; }
}
public class Price
{
public string currencyIso { get; set; }
public double value { get; set; }
public string priceType { get; set; }
public string formattedValue { get; set; }
public string type { get; set; }
}
public class Result
{
public string code { get; set; }
public string name { get; set; }
public Stock stock { get; set; }
public Price price { get; set; }
public List<Image> images { get; set; }
public List<object> categories { get; set; }
public string pk { get; set; }
public List<string> sellingAttributes { get; set; }
public WhitePrice whitePrice { get; set; }
}
public class Root
{
public List<Result> results { get; set; }
}
ok, and these append to my current code? as new objects for each of these fields in the .cs file?
If the JSON is
you can't deserialize it to
You place those wherever
You send a
Get
request to the API and get a JSON string back
Then you use (ugh) Newtonsoft.Json to deserialize that JSON to the Root
classok, so the object has to match exactly to the fields of the JSON, so each section of the JSON I want to use needs to be treated like an object?
so in the example above:
Objects need to be treated as objects, lists as lists
this would satisfy the JSON conversion to extract the image results?
But yes
Yes, but you'll get a list of images
ok, and some of the lines it complains about:
do these need their own classes defined as well?
Yes, unless you don't need them
Or can they be removed if i dont need them
ok got it
so how can I extract into these classes from the response?
If I wanted to get like, pants and a shirt, and get the name and image for each
I added in newstonsoft
Then the
data
will be an instance of YourCoolClass
ok, so would coolclass be the root in this instance?
Yep
Also, since you're using
async void
it'll swallow exceptions. Not sure how Unity handles asynchronous button clicks and stuff, though
So wrap the whole thing in a try catch
, log the exception, and later on look into how it should be done properlyit says JsonConverter has no Deserialize def
Idk, maybe
Convert
or something?
Haven't used Newtonsoft in years
See what IntelliSense tells youbut it isn't auto suggesting here:
Try
JsonConvert
yeah that one works
so this root class isn't static, do I need to create an object of it to get fields? And what about the other classes and filling their data?
Nope. the Deserialize method will create the object and return it populated
it's smart enough to instantiate all the types that it needs
ok, would i be able to debug.log the data object itself?
or I guess, what can I do with this data var now?
using the new snippet returns a 401 error
Use your original code to get the response
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
// Deserialize code
var data = JsonConvert.DeserializeObject<Root>(body);
Debug.Log(body);
}
We got a little wrapped around how you were sending and getting the data before we knew it was unity and there was an api key involvedso where would fit into this?
just replacing it with var data = JsonConvert.DeserializeObject<Root>(json); ?
I created two objects:
the deserialize snippet returns the body in the debug but the objects are remaining empty in inspector
snippet:
to be clear, current file:
(not including the classes below it)
I also tried
but the body debug always returns the info and the root/result objects are still blank in the inspector
Why do you create those instances?
No need to
I'm just trying to still figure out how to get this data into a manipulatable state
JsonConvert.DeserializeObject<Root>(body)
will return an instance of Root
would do the same?
I realized JsonUtility was added to Unity
Idk, maybe?
ok, so i have an instance of root, I can't see it anywhere though, how would I go from this deserialized root to getting the name of the item
root
that instance
And you would use... the properties of it
If it has an Images
property, well, access it
root.Images
If Images
is a list, well, treat it as a list and loop over it, or get n
th elementi see this:
I threw your code into a Console app, and I'm getting data back
Yeah, Root doesn't have that
it has a List<Result>
Look at the class you have
It'll give you all the information you need
ok @Axiss do I need to create an Image object?
no
You need to navigate the deserialized object
root.results is a list
each result has the properties you are looking for
ok, let me try that
if I debug log the root.list I get:
*root.results
Yeah, that's expected
you handed Debug.Log a List<Result> and it wrote out it's name
What are you trying to do with these results?
I just need the name of the item and the photo of it
Access and log those, then
I'm not understanding how to do that, i have serializable classes for Image and Result but do not know how to fill them
You don't fill them
You don't even instantiate those classes manually
The deserialization does that for you
Ok, so with How would I debug.log the image url after deserializing root?
From...
root
See what properties it has
And traverse them until you get to the imageslooking through here?
Here, and looking at the class
results
is a list in this case
So... treat it as a listlike ?
It is an array/list
What can you do with a list?
You can loop over it for example
Your api call returned 30 results
right, but its giving me what looks like garbage in the debug log:
```
That's why you loop over it...
Loop
Loop
Loop
Loop
there isn't A image and A name
An array or a list will never be converted to a string properly
@Axiss yes, that is what it does in the tests online, 30 results for any of the tags i enter in this case "men_trousers"
Not will a random class
ok, sorry again I am new to this, so how would i go about looping over this?
You need to go over the results, and get the data of each object, as needed
With... a loop
foreach (var whatever in root.results)
ok, one sec, I know the syntax for a loop i didnt know what to put in
would something like this be on the right track?
item
is a class
So you'll also get garbage output to the console
Try one of the properties of itemohhhh
one sec
im using , also used item.images and am getting garbage, so I need to set this 'item' as a list?
like, item.name is returning what seems to be what I want:
images is a list
so you need to loop through it to read it
so like:
not quite
image is an object, with properties
public class Image
{
public string url { get; set; }
public string baseUrl { get; set; }
}
you'll need to access image.url or image.baseUrl
Angius#1586
REPL Result: Success
Console Output
Compile: 743.247ms | Execution: 125.938ms | React with ❌ to remove this embed.
I don't seem to be able to just append it with .url:
The
image
will have the url
item.images
is a list of images
Again, look at the classes you haveok, i see that now
sorry, would these terms be considered accessors? How would I be able to read up on knowing how to access stuff like this in the future? the snippet above is helpful as well
so what I have now is
which works
Properties are what they are called in the C# world
Properties do stem from accessor methods, so I guess you could Java-ify the concept to that
$getsetdevolve
can be shortened to
can be shortened to
can be shortened to
can be shortened to
ok now that i understand how to access these properties I think I have almost everything I need
i want to randomize a choice from 1 to 30 for the three seperate calls i will be making for the three seperate item types
I can randomize something like:
to choose
I guess my only other question is, should I simply call this three times if I need say a shirt, a coat, and pants? the string there needs to be changed to the accessor for the categories such as
Depends on the API
Can you get all of those things in a single call? Do
You can't? Well, not much can be done besides calling the API multiple times
That I am unsure of, is there a way to test it? The api seems pretty barebones: https://rapidapi.com/apidojo/api/hm-hennes-mauritz/
RapidAPI
HM - Hennes Mauritz API Documentation (apidojo) | RapidAPI
H&M API helps to query for all information about regions, categories, products, etc... as on official websites
I just want to try to use good programming practices and minimize calls if I can, if not that is fine
Right now I have it set up barebones like:
and will just interpolate the url three times, one for each clothing category
The documentation of the API is how you learn about it
Right, this format is new to me, is there something I am missing in terms of docs here? or is it just reading through each GET and seeing what they accept?
Yeah, just see what they accept and what they return
Well it just provides an httpclient example from what I can see, and no mention of multiple calls at once:
this would be for GET products/list
I guess it might be hard to really request multiple of the same GET anyway, since I want to basically call one request, get an item from that category, then run the script again with a different request of category
Thank you for your help @Angius and @Axiss I'll take a look at optimizing my code and working further on this, I might post a question when it is finalized but I think this is about as much info as I need to continue. Sorry for not knowing much lmao
You're welcome!
Anytime
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.