0

I have this query

http://localhost:8555/list/csv?search={}

Where search is a json object (omitted other params as they are irrelevant here). How can i convert this into a nested object?

public record CsvParams<T>(
    T search,
    /* Other query params */ ) {}

Right now im getting error that string cannot be cast into object.

class java.lang.String cannot be cast to class classname

Is there anyway to do this? Old solution uses ObjectMapper to convert string into corresbonding object. I was hoping that maybe there is a way to do it more simpli and remove this boilerplate.

Marko Taht
  • 1,448
  • 1
  • 20
  • 40
  • Java natively doesn't support JSON parsing. Using an ObjectMapper is probably the most optimal solution. – berse2212 Jan 23 '23 at 14:22
  • All the endpoints go through Jackson. Since that is what spring uses. Maybe some jackson xconfig can help here or some annotation? – Marko Taht Jan 23 '23 at 14:23

2 Answers2

1

Any single value of a query param can't be automatically converted to a non-primitive type. You can convert multiple params to a class, but not one that happens to be a JSON AFAIK. But you can create a converter custom deserialiser and then use it in different controllers, but in the end you'd still use an ObjectMapper.

More info on how to do the latter here: https://www.baeldung.com/spring-mvc-send-json-parameters

Tarmo
  • 3,851
  • 2
  • 24
  • 41
  • But can i make somesort of a generic serializer? Or do i need a spesific serializer for each instance? – Marko Taht Jan 23 '23 at 14:43
  • Theoretically you can, if your object would be wrapped into something generic (like in your case `CSVParams` then T could possibly be generic I think). Then you would register only this one converter for your wrapper type. Because you can deserialise generic types with `ObjectMapper` https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class. But I'm not sure and I don't have the means to try out if it really works and I'm not sure if it's possible to make it play well with validation. – Tarmo Jan 23 '23 at 14:49
  • It seems that i cannot get the class data into the deserialziers. Its lost on the way... – Marko Taht Jan 23 '23 at 15:42
0

If you have to work with query params than I don't think you can have it converted automatically by Spring boot. But if you work with POST or PUT methods and can pass your params as request params in request body your JSON params can be automatically converted to class instances by Spring boot and no effort required from you. However, if you have to work with query param (say you have to use method GET so you have no request body) than you can use Json-Jackson library or Gson library to parse your Json into class instance. If you use Jackson you will need to use class ObjectMapper. For Jackson lib info see this site, for ObjectMapper class see Javadoc here. However, I wrote my own JsonUtils that is very good for simple usecases like yours. It allows to to parse simple JSON into a class with a single method. It is very simple and strait forward. It is a thin wrapper over Jackson library. See the Javadoc for method readObjectFromJsonString. Class JsonUtils is part of Open Source MgntUtils library. You can get it as Maven artifact on Maven Central and as a jar (with source code and Javadoc) on Github

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
  • Right but what if i unest the Object. like @GetMaping() public void method(SearchType search, /* other params */){} Can i create somsoert of a formatter for this situation? Something generic that can handle this, since This way its not a generic object there, its a concrete object that i need to convert form JSON. (Spring already uses Jackson) – Marko Taht Jan 24 '23 at 09:08
  • @MarkoTaht I am not sure I undestand your comment. First while Spring doers use Jackson by default it could be configured to Gson as well and for method GET it is irrelevant as query parameters you always get one by one as primitives. They are not converted. I think you can get them as a Single map and that may make your life a bit easier – Michael Gantman Jan 24 '23 at 11:37
  • I have 1 parameter that is JSON. I want it to be a spesific object. So if instead of using String and Int and what not, could i use my className there and have Spring convert this json into the object. Like i have 10 parameters coming in. 1 of them is a JSON. – Marko Taht Jan 24 '23 at 14:30
  • If you use GET method than no you won't be able to have Spring convert your param automatically. Say if you know in your code that param by certain name comes as JSON representation of a particular class you can parse the param value by one of the ways I mentioned in the answer. If you don't know the name of the class add the classname as additional param and than parse it. Or you can always parse it into a Map. But either way you will have to do it on your own. You will have to take your param as a string and parse it in your code. – Michael Gantman Jan 24 '23 at 15:09
  • Well thats just sad. – Marko Taht Jan 24 '23 at 17:40