Skip to content

ACCEPT_SINGLE_VALUE_AS_ARRAY doesn't work on Guava ImmutableList #185

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

Open
JGergely opened this issue Jun 14, 2023 · 2 comments
Open

ACCEPT_SINGLE_VALUE_AS_ARRAY doesn't work on Guava ImmutableList #185

JGergely opened this issue Jun 14, 2023 · 2 comments
Labels

Comments

@JGergely
Copy link

Describe the bug
When defining a Guava ImmutableList on org.immutables.value.Value.Immutable objects to correctly deserialize both from a single JSON object and also from an array with the ACCEPT_SINGLE_VALUE_AS_ARRAY annotation on the field it fails to do so.

In case of using a java.util.List instead of the Guava type it works. Not sure if issue is within Jackson itself or somewhere else, please advise.

Version information
2.14

To Reproduce
To reproduce I created an Immutable type with a single list field which should accept both a single object and an array as a JSON input (set with ACCEPT_SINGLE_VALUE_AS_ARRAY).

@Value.Immutable
public interface ExampleInterface {
  @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
  ImmutableList<ExampleLine> getLines();
}

@Value.Immutable
public interface ExampleLineInterface {
  String getData();
}

class Scratch {
    public static void main(String[] args) {
         /*
            { 
                lines": 
                {
                    "data": "something"
                }
            }
         */
        String example = "{ " +
                "           \"lines\": \n" +
                "           {\n" +
                "             \"data\": \"something\"\n" +
                "           }" +
                "         }";
        try {
            Example actual = getObjectMapper().readValue(example, Example.class);
            System.out.println(actual);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    private static ObjectMapper getObjectMapper() {
        return JsonMapper.builder()
                .visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
                .visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY)
                .visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
                .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
                .enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)
                .enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)
                .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)
                .enable(MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES)
                .disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
                .disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                .addModule(new GuavaModule())
                .addModule(new FormattedNumberIdModule())
                .addModule(new JavaTimeModule())
                .addModule(new Jdk8Module())
                .addModule(new ParameterNamesModule())
                .build();

    }
}

throws

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.google.common.collect.ImmutableList<java.lang.Object>` from Object value (token `JsonToken.START_OBJECT`)
 at [Source: (String)"{            "lines": 
           {
             "data": "something"
           }         }"; line: 2, column: 12] (through reference chain: com.picnic.supplierinterface.edeka.reddi.api.model.Example$Json["lines"])

while the same thing but with a java.util.List type:

@Value.Immutable
public interface ExampleInterface {
  @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
  List<ExampleLine> getLines();
}

deserializes correctly and prints:

Example{lines=[ExampleLine{data=something}]}
@cowtowncoder
Copy link
Member

Ok, I strongly suspect this is not something Jackson handles, but things do get hairy with combinations of so many pieces.

One thing that might help would be to first see if direct use of ImmutableList (from Guava) would work, without Immutables framework. If not, it's likely Guava module's problem (and if so, should move/file issue there).

@JGergely
Copy link
Author

Thanks, I'll check and report back!

@cowtowncoder cowtowncoder transferred this issue from FasterXML/jackson-databind Apr 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants