On Tuesday, April 16, 2019 at 5:05:14 PM UTC-4, Tatu Saloranta wrote:
>
> On Tue, Apr 16, 2019 at 1:05 PM Chris C <yahoo...@gmail.com <javascript:>> 
> wrote:
>
>> I have a map of type 
>>
>> Map<Key1, Map<Key2, Integer>>
>>
>>  that I want to serialize to json to store in as a field in a database 
>> record.
>>
>> Key1 and Key2 are my own classes with getters defined and the 
>> constructors annotated as JsonCreators.
>>
>> I have been able to process single level maps for the same purpose by 
>> configuring the type factory for the object mapper, but I am unsure how to 
>> go about it for nested maps with different keys.
>>
>
> There are 2 challenges:
>
> 1. Expressing `JavaType` to use for deserialization (serialization is 
> usually fine, although if you try to serialize Map as root value [Strongly 
> Discouraged practice!], then there too)
>


Can you explain what you mean please?  


2. Allowing custom Map key types -- may need to register Key deserializers, 
> key serializers (common types like `String`, `Number` supported out of the 
> box)
>      - note: Map keys must be scalar types; read from String, written as 
> Strings
>
> First one is done using `TypeFactory`, either with TypeReference:
>
>    JavaType mapRef = typeFactory.constructType(new TypeReference<Map<Key1,
>  Map<Key2, Integer>>>) {} ())
>
> Or constructing it in two parts, something like
>
>    JavaType mapRef = typeFactory.constructMapType(Map.class, 
> typeFactory.constructType(Key1.class),
>        typeFactory.constructMapType(Map.class, 
> typeFactory.constructType(Key2.class), 
> typeFactory.constructType(Integer.class)));
>
> Second part may be more involved, but if you have already handled 
> non-nested maps with custom types, you probably know how that works.
>
>
I didn't even think to chain the type factory calls here.  Before I tackle 
the deserialization I ran into serialization.

Expanding on the structure I have the following (was using 
https://www.baeldung.com/jackson-map as a starting point)

public class Basket {
    // other fields


    // this is what I am trying to de/serialize separately
    private Map<Seller,Map<BasketItem,Integer>> contents;


    // other stuff removed



    @JsonSerialize(using = Seller.Serializer.class)

    public static final class Seller {
        private final Long id;
        private final String name;
         @JsonCreator
        Seller(@JsonProperty("id") Long id, @JsonProperty("name") String 
name) {
             this.id = id;
             this.name = name;
         }



         // getters, equals, hashcode, tostring


        public static class Serializer
        extends StdSerializer<Seller> {

            private static final long serialVersionUID = 1L;

            public Serializer() {
                super(Seller.class);
            }

            public Serializer(Class<Seller> t) {
                super(t);
            }

            @Override
            public void serialize(Seller seller, JsonGenerator jsonGenerator
, SerializerProvider serializerProvider)
            throws IOException {
                jsonGenerator.writeStartObject();
                jsonGenerator.writeNumberField("id", seller.getId());
                jsonGenerator.writeStringField("name", seller.getName());
                jsonGenerator.writeEndObject();
            }
        }
    }


    @JsonSerialize(using = BasketItem.Serializer.class)
    public static final class BasketItem {

        private final Long itemId;

        private final String itemName;

        private final Price unitPrice;

        @JsonCreator
        BasketItem(@JsonProperty("itemId") Long itemId,
                   @JsonProperty("itemName") String itemName,
                   @JsonProperty("unitPrice") Price unitPrice) {
            this.itemId = itemId;
            this.itemName = itemName;
            this.unitPrice = unitPrice;
        }

        // getters, equals, hashCode, toString

        public static final class Serializer
        extends StdSerializer<BasketItem> {

            public Serializer() {
                super(BasketItem.class);
            }
            public Serializer(Class<BasketItem> t) {
                super(t);
            }

            @Override
            public void serialize(BasketItem basketItem, JsonGenerator 
jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
                jsonGenerator.writeStartObject();
                jsonGenerator.writeNumberField("itemId", basketItem.
getItemId());
                jsonGenerator.writeStringField("itemName", basketItem.
getItemName());
                jsonGenerator.writeObjectField("unitPrice", basketItem.
getUnitPrice());
                jsonGenerator.writeEndObject();
            }
        }
    }

}


public final class Price {
    private final BigDecimal amount;

    // this is an enum
    private final Currency currency;

    @JsonCreator
    public Price(@JsonProperty("amount") BigDecimal amount, @JsonProperty(
"currency") Currency currency) {
        this.amount = amount;
        this.currency = currency;
    }


    // getters, equals, hashCode, toString
}




When I try to serialize this using either

String json = new ObjectMapper().writeValueAsString(contents)


or 

final ObjectMapper mapper = new ObjectMapper();
final SimpleModule module = new SimpleModule();
module.addSerializer(BasketItem.class, new BasketItem.Serializer());
module.addSerializer(Seller.class, new Seller.Serializer());
mapper.registerModule(module);
String json = mapper.writeValueAsString(contents);


it uses my toString(), but not the serializer from the annotation. If I 
remove my toString, it falls back to Object.toString(). 

No exceptions are being thrown. Why is my Serializer not being used?

After that, what do I need to implement and register for deserialization?


Thanks

Chris

-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jackson-user+unsubscr...@googlegroups.com.
To post to this group, send email to jackson-user@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to