✅ How to parse this weird API ?
I have a very akward thing to do and I d'ont know if there is a clean way to do it.
In a REST API, there is two string fields
In my Domain I have a class with all possible properties
what I need to do is, depending on the AttributeName and AttributeValue given in the API, I want to create an instance of Product which has all everything equal to null except for the property for which we were given the name and value in AttributeName and AttributeValue. (there is always a single one) For exemple
attributeName
and attributeValue
(for example { "attributeName" : "isAllowed" , " attributeValue" : "true"}
and { "attributeName" : "productType" , " attributeValue" : "A50"}
, in the API this is modelled by the following class
N.B: the "attribute" here have nothing to do with any .NET vocabulary, it's just a name, think of it like "foo" or "bar"
In my Domain I have a class with all possible properties
what I need to do is, depending on the AttributeName and AttributeValue given in the API, I want to create an instance of Product which has all everything equal to null except for the property for which we were given the name and value in AttributeName and AttributeValue. (there is always a single one) For exemple
{ "attributeName" : "isAllowed" , " attributeValue" : "true"}
would result in a product
Instance with product.IsAllowed = true
and product.ProductType = null
(and other fields will be null as well)
Another example, { "attributeName" : "productType" , " attributeValue" : "A50"}
would result in product
Instance with product.IsAllowed = null
and product.ProductType = A50
(and other fields will be null as well)64 Replies
.
my attempt is something that i find very ugly:, it's something like this:
for 10 properties to handle, it will be a huge mess :/
Any help ?
make a method in
ApiCommand
that maps to Product
btw, ApiCommand
is what we call a data transfer object (DTO), and the conventional way to name it is ProductDTO
oh wait
i think i misunderstood youhttps://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/reflection-and-attributes/ try reflection maybe can help
Attributes and reflection
Use attributes to associate metadata or declarative information with code in C#. An attribute can be queried at run time by using reflection. Reflection provides objects that describe assemblies, modules, and types in C#. If your code includes attributes, reflection enables you to access them.
ApiCommand
returns the value of a single property for a product?
thats not what they mean by attributeyeah, attribute belongs to a domain vocabulary, that have nothing to do with the meaning of an attribute in C# 😆
I will edit my Original post to be more clear
^
yup
ApiCommand
always have the name and value of a signle property of productwhat a shitty api
so that means you need to query the endpoint for each property of
Product
?no it's more complicated
I tried to create a simple example to be able to communicate what I need to do
unfortunately I don't have the ability to change the ApiCpmmand
you can think of it as a product will always have everything null except for one property
i dont see how thats different from what i said
i understand that. reflection can help you access metadata like
im aware
at that point i didnt understand op's question
but yeah that could be useful, although i still dont fully understand what op is trying to do lol
The endpoind is a POST. When the body has
{ "attributeName" : "isAllowed" , " attributeValue" : "true"}
it would result in creating a Product
Instance with product.IsAllowed = true and product.ProductType = null (and all other properties will be null as well). That instance will then be saved in the Dbah
and you just need to set this one property in your model
yup
everytime it's just one property
do you make the post req in the same app?
obviously, that was a stupid question
lol i meant to ask, how do you make the post requeist
how do you provide
attributeName
it's exposed by my app to the users who have some client coded
wait youre writing the api?
so youre recieving the post request?
the
ApiCommand
instance?yup
ah
alright, you have 2 options:
1. use reflection
2. write a source gen
id go with 1 in your case
😢
I feel that it's very shitty
its not
its made for things like this
thats what a lot of serializers use
actually theres a third option
re design your api
I can't :(, it's designed by some """"""tech lead""""""" :/
oof
welp
reflection it is
If it was me I would go with something that mirror
Product
in the Api :/yes thats what sane people would do
unless im missing some context
if I try to do this using reflection, can't see how this is helpful :/
(it's the message posted by @daysleeper00 )
ah, Model here is
Product
?
I thought it was ApiCommand
you can first validate fields by searching for them and then invoke a method like UpdateFields() where invoke property.SetValue(). i think its pretty easy if you research a bit about reflection
well what you want to do is get the property named
ApiCommand.attributeName
Type.GetProperty Method (System)
Gets a specific property of the current Type.
but i still need to compare apiCommand.AttributeName with property.Name for every preperty in
properties. = Product.GetProperties()
right ?no
read the doc i sent
GetProperty
returns null if the property doesnt exist
actually maybe that would be faster
if you cache the property infosstill can't see how to use it 😆 , something like
product.GetProperty("isAllowed")
won't help me
the input is ApiCommand
. and not the Product
read about reflection first and when you understand how it works you will get this done trust me
okay !
did you read this?
How many properties are there? Are they likely to change in the future?
this is in a post endpoint
theyre recieving an
ApiCommand
instance, and they want to create a Product
and set the property that is in ApiCommand
thats the TLDRI'm aware.
ah
I'm asking for how many properties there are on
Product
oh
if its a low number, and not likely to change, a reflection based approach seems overkill
oh yeah if its low enough you could switch on
ApiCommand.balblaName
idk why i didnt think of thatactually, a source generator would be a very cool solution.. and also very likely massively overkill in terms of effort 😄
exactly
there is ~15 properties
alright. thats... doable on a switch, but might not feel very clean.
I did but not sure I fully understand it :/. It lacks some examples
look at the last overload
Type.GetProperty Method (System)
Gets a specific property of the current Type.
i guess I need to do something like
the second part will have nasty syntax.. something like
property.SetValue(product, value);
where value
is a correctly typed variable holding the parsed content from AttributeValue
string, just shove it in. int/bool etc? gotta parsetypeof(Product).GetProperty
although caching the property infos and querying them might be a faster approach, if you care about performance
you should benchmark it first thoyeah that feels like a very strange syntax
yup, I also need to parse strings to properly tyed stuff
what do you mean by caching it ?
storing it somewhere and accessing it
not using reflection to get all the properties every time
Okay, I will give reflection a try, then benchmark it and then maybe cache it in some config file (app.settings for instance)
dont cache it in a config file
that wouldnt work anyway
cache it in the class youre doing that in
you'd set up a dictionary or similar, between your string (property name) and the propertyinfo
and calculate that once, at startup
because reflection is expensive (time-wasting)
so doing it once and then storing the results is good practice
oh right thats a better idea
what do you mean by "propertyInfo" ?
look at what this returns
Thats the type you get from
typeof(T).GetProperty
Oh yeah I see, it's still using relfection by only once using some static field to store the result
thanks folks
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.