#Jackson Mapper - String[] conversion possible?

28 messages · Page 1 of 1 (latest)

tawny salmon
#

This should be trivial, but I cannot figure out how to do it. In looking at custom annotations and additional registered serializers, I must be missing something.

`import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.impl.StringArraySerializer;

public class ExampleDto {
@JsonSerialize(using = StringArraySerializer.class)
public String[] field;
}

public class ExampleDtoTest {
@Test
public void testConvertToMap() {
HashMap<String, Object> expectedMap = new HashMap<>() {{
put("field", (new String[]{"1","2","3"}));
}};

    ExampleDto exampleDto = new ExampleDto();
    exampleDto.field = new String[]{"1","2","3"};

    ObjectMapper mapper = new ObjectMapper();
    HashMap result = mapper.convertValue(exampleDto, HashMap.class);
    assertEquals(String[].class, result.get("field").getClass()); // fails
}

}`

worthy heartBOT
#

This post has been reserved for your question.

Hey @tawny salmon! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

gaunt wren
#

Use a List<String>. In Java 11 you can use List.of to make one

shut valve
#

Wait, what are you testing? Why do you care what convert(object, HashMap.cass) does?

tawny salmon
#

The test is to demonstrate the conversion to ArrayList. The question is how to convert a String[] property into a Hashmap<String, Object> with a <String, String[]> entry instead of the coerced <String, ArrayList<String>> entry.

#

I believe what is happening is that the serializer is called to make json, which is then tokenized with a json parser. Then the jackson json parser is used to make the HashMap.class, which has a default jackson serializer. In order to ensure type safety of each element of an array, it uses an ArrayList. So the String[] type disappears.
Making a ~50ln deserializer works to coerce the type back to String[] - but that seems overkill. Is there any other way? I would imagine this has come up before for Jackson.

shut valve
#

But... Jackson is for converting to JSON, not to arrays.

tawny salmon
#

[1,2,3] is simpler datatype that exists in JSON than ArrayList(){{ 1,2,3 }}.

The question remains, other than a fairly robust deserializer to a mapper as a module, is there a simpler way?

shut valve
#

You just refuse to develop your thoughts regarding my observation?

tawny salmon
#

I don't understand.

shut valve
#

Jackson is for converting to JSON, not to arrays. What can possibly make it so you care whether that convert above will give out an array or a List?

tawny salmon
#

This isn't relevant. The question is about methodology, not circumstance. Why I care is that I am trying to figure out a way to do it, beyond my current solution. Let's just assume I can't control the source datastructure (it's part of another API in jar), does that matter? No.

#

I have another API that needs a HashMap and it can only handle primitive members and primitive arrays.

shut valve
#

You do understand how much this is guaranteed to be an X/Y problem?

tawny salmon
#

@JsonSerialize addresses this same X/Y problem, from a different direction. I don't understand the avoidance.

shut valve
#

.... No. Jackson does the job it is expected to do. Whether internally arrays or lists are involved is none of the business of whoever isn't making Jackson itself.

tawny salmon
#

This is incorrect. Jackson provides a conversion API via convertValue.

#

They implement a defaultSerializer which does not involve json

shut valve
#

That it provides that changes none of the previous observations.

tawny salmon
#

This was a long-winded way of saying "I don't know and don't care". GL with whatever.

shut valve
#

This was a long-winded way of confirming you're guaranteed to be in a X/Y problem situation, which experts on the domain may be uninterested in. But you do you.

tawny salmon
#

The following seems overkill, but it works (more or less, no float etc) added as:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(HashMap.class, new CustomDeSerializer()); mapper.registerModule(module); HashMap<String,Object> result = mapper.convertValue(exampleDto, new TypeReference<>(){});

tawny salmon
#

If you can make due with the bytes as an Object[], rather than a String[] ,
mapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);

tawny salmon
#

ObjectMapper mapper = new ObjectMapper(); MapType collectionType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, String[].class); HashMap<String,Object> result = mapper.convertValue(exampleDto, collectionType);
This is an initialization that is needed to pass the test. It does not survive additional field types, but it does avoid the conversion to ArrayList succinctly.

worthy heartBOT
# worthy heart

Before your post will be closed, would you like to express your gratitude to any of the people who helped you? When you're done, click I'm done here. Close this post!.