-
-
Notifications
You must be signed in to change notification settings - Fork 158
JsonConverterAttribute for Query Params #1275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @boginw, thanks for your proposal. I tried a few things, but am unable to reproduce what you're describing. Can you please provide a complete example demonstrating your use of And what does your HTTP request(s) look like? Do you want to filter on the individual parts? And what would the JSON response body look like? |
Hi @bkoelman Of course, I've set up a test repository showcasing the issue: https://github.com/boginw/json-api-dot-net-query-params-feature The project contains a single resource For convenience, you can fetch curl --location 'http://localhost:5000/weather-forecast' That should return 5 randomly generated We can also send a curl --location 'http://localhost:5000/weather-forecast' \
--header 'Content-Type: application/vnd.api+json' \
--data '{
"links": {
"self": "http://localhost:5000/weather-forecast",
"first": "http://localhost:5000/weather-forecast"
},
"data": {
"type": "weatherForecasts",
"attributes": {
"date": "2023-05-24",
"temperatureC": 48,
"summary": "Sweltering",
"wrapper": "128540050,243020457"
},
"links": {
"self": "http://localhost:5000/weather-forecast"
}
}
}' But as soon as we try to filter by curl --location "http://localhost:5000/weather-forecast?filter=equals(wrapper,'123,321')" It fails with:
|
Thanks for the steps, makes sense now.
Actually, it matters a lot how data is stored and queried. I was unable to use To make sort/filter work in the database (and be efficient on large tables), it needs to be translated to SQL. For that to happen, EF Core must be able to "read through" your wrapper. There are various ways to do that, such as:
Therefore it matters greatly how you expect API clients to interact with the data inside the wrapper, and how it is stored internally. There's also ASP.NET ModelState validation to consider, which uses reflection to descend into objects. I do not see usage of Opening up the static I suspect there's an easier/better way to achieve what you need, using existing features. And I'm willing to guide you in the right direction, but I need to understand the big picture, to be of help. So please explain your use case by providing a more realistic sample that you'd potentially put into production, including a database, etc. Could you try adding your customizations to the GettingStarted sample and see if you can get that running? |
Thank you for your detailed response and suggestions. I've made some updates to the test repository and included the GettingStarted sample with the necessary modifications to demonstrate the issue. In the modified GettingStarted sample, I've added the However, the issue still persists when trying to filter on the
In the original and the GettingStarted projects, the The name Based on your experience with JsonApiDotNetCore, are there any existing features or approaches that you would recommend for handling custom-type conversions in query parameters? I would greatly appreciate any guidance you can provide in this regard. Thanks :) |
Well, it works out a lot better than I expected! That's mainly because you're acting at the type level. I expected the
Likewise, when sparse fieldsets are used, JADNC generates a LINQ query such as:
So it just copies existing I discovered that ModelState validation does not run for I've been playing with opening up the filter parser and found the issue you reported affects the following filter functions (no other query string parameters):
Passing a custom type converter works for all of them, except Back to your scenario: wouldn't it be easier to just expose the product ID and variant as separate JSON:API fields and store them in separate database columns? That would enable more powerful filters, such as: Options, with some pointers:
I'm gonna be out in the upcoming days and will get back to this next week. |
Correction: It works for I'm trying to implement custom query string value converters, but I've found no way to make text-matching work, even with custom converters in place. source
.Where(item => item.Product.ToString().EndsWith("-XL))
.OrderBy(item => item.Id)
.Take(10) fails with:
This makes me wonder if going this route makes sense at all.
So why not just store it in separate database columns, which gives you all the JSON:API capabilities out of the box? |
Thank you for your detailed analysis and suggestions, and sorry for this late response. I understand your points about the limitations of using a custom type converter for substring match functions and the benefits of storing the data in separate database columns. However, in our specific use case, we have a requirement to keep the product ID and variant together as a single entity. This is due to some business logic that treats them as a single unit. Splitting them into separate fields would complicate this logic and potentially introduce errors. I understand that this approach has its limitations with respect to JSON:API capabilities. However, we are willing to work within these limitations given our specific requirements. I'm interested in exploring other potential solutions that could work within our constraints. For example, could we possibly extend the filter parser to handle our custom type? Any further guidance you could provide would be greatly appreciated. |
So if I understand correctly, you'd like to:
This makes me wonder why the If input validation is desired, this is best solved using a resource definition that validates the incoming attribute value (see https://www.jsonapi.net/usage/common-pitfalls.html#jsonapi-resources-are-not-ddd-domain-entities). I'm not saying no to extending filter parsing; it's just something unavailable today. I'd like to address that, but it's related to #1277 and I'm not sure yet how to best solve that. |
Closing due to inactivity. Please comment if you need this to be reopened. |
Is your feature request related to a problem? Please describe.
Currently, in the serialization and deserialization of request bodies, the
JsonConverterAttribute
is considered, allowing for custom conversion logic to be applied. However, when it comes to filters, this attribute is ignored. While this behavior is expected since query parameters are not in JSON format, there are cases where it would be useful to apply certain conversions.Consider the following scenario where a custom-type
Wrapper
and its correspondingWrapperJsonConverter
are used:Currently, when
new Wrapper("part1", "part2")
is serialized and included in a request body, it is correctly converted to"part1,part2"
. However, if the client attempts to use a query parameter likeequals(wrapper, 'part1,part2')
, it will encounter aQueryParseException
with the message "Failed to convert 'part1,part2' of type 'String' to type 'Wrapper'." This can lead to confusion and frustration, as the only way forward, is the take the fields from Wrapper and adding them wherever needed.Describe the solution you'd like
To address this limitation, I propose enhancing
RuntimeTypeConverter
to support custom type conversions for query parameters as well. This feature would enable developers to define their own conversion logic for custom types when processing query parameters, similar to how it's done for request bodies.Describe alternatives you've considered
An alternative approach to address the serialization and deserialization of custom types in query parameters could involve utilizing the
JsonApiResourceDefinition
. In this scenario, theWrapper
class could be treated as a resource, and a correspondingJsonApiResourceDefinition
could be created. However, sinceWrapper
isn't a resource, this would not be advisable.The text was updated successfully, but these errors were encountered: