Skip to content
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

CollectionSerializer gets confused on how to handle elements #450

Closed
ghost opened this issue Apr 30, 2014 · 3 comments
Closed

CollectionSerializer gets confused on how to handle elements #450

ghost opened this issue Apr 30, 2014 · 3 comments

Comments

@ghost
Copy link

ghost commented Apr 30, 2014

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.util.StdConverter;
import org.junit.Test;

public class BugTest {

    private static class Base {
        @JsonProperty
        @JsonSerialize(contentAs=Inner.Serializable.class)
        private List<Inner> innerList = new LinkedList<Inner>();
    }

    private static class Inner {
        /**
         * Work around for: https://github.com/FasterXML/jackson-databind/issues/357
         */
        @JsonSerialize(converter=InnerConverter.class)
        public static class Serializable extends Inner {}

        @JsonProperty("0")
        private String stringProperty;

        @JsonProperty("1")
        private int intProperty;
    }

    private static class InnerConverter extends StdConverter<Inner, List> {

        @Override
        @SuppressWarnings("unchecked")
        public List convert(Inner value) {
            List list = new LinkedList();

            Map map = new ObjectMapper().convertValue(value, Map.class);
            for(int i = 0; i < map.size(); i++)
                list.add(map.get(String.valueOf(i)));

            return list;
        }
    }

    @Test
    public void test() throws Exception {
        Inner inner1 = new Inner();
        inner1.stringProperty = "abc";
        inner1.intProperty = 123;

        Inner inner2 = new Inner();
        inner2.stringProperty = "def";
        inner2.intProperty = 456;

        Base base = new Base();
        base.innerList = Arrays.asList(inner1, inner2);

        assertEquals("{innerList: [[\"abc\", 123], [\"def\", 456]]}", new ObjectMapper().writeValueAsString(base));
    }
}
com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.lang.String and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: Base["innerList"]->java.util.ArrayList[0]->java.util.LinkedList[0])
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26)
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContentsUsing(CollectionSerializer.java:145)
@ghost
Copy link
Author

ghost commented May 1, 2014

A deserialization converter works in this manner, so as a work-around, I am using a Serializer instead of a converter on the serialization side.

...
    private static class InnerSerializer extends StdSerializer<Inner> {
        protected InnerSerializer() {
            super(Inner.class);
        }

        @Override
        public void serialize(Inner value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
            jgen.writeStartArray();
            Map map = new ObjectMapper().convertValue(value, Map.class);
            for(int i = 0; i < map.size(); i++)
                jgen.writeObject(map.get(String.valueOf(i)));
            jgen.writeEndArray();
        }
    }
...
JSON: "{innerList: [["abc": 123], ["def", 456]]}"

JSON  ->  deserialization via converter  ->  POJO  ->  serialization via serializer  ->  JSON

@ghost
Copy link
Author

ghost commented May 3, 2014

Quick update. In the case anyone comes across this, I solved my root problem in a much, much simpler way by using:

@JsonFormat(shape=JsonFormat.Shape.ARRAY)
@JsonPropertyOrder({"stringProperty", "intProperty"})

I should have known there was a way to do this natively, I just didn't look hard enough.

@ghost ghost closed this as completed May 3, 2014
@cowtowncoder
Copy link
Member

@roguefrequency ah yes. This is yet another feature that is not widely known, or extensively documented. I have blogged about it a bit, but it needs to catch on so there'll be more google hits :)

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant