On Wed, Apr 17, 2019 at 9:02 AM Chris C <yahoono...@gmail.com> wrote:
>
> 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> 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?

Which part?

>> 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)

This is only "value" serialization: values of this type as POJO
property values. But it is not
But it is NOT used when serializing Map keys. This because Map keys
(and POJO property names, that is, name part of JSON objects).

There is actually `keyUsing` equivalent, but that is only for `Map`
types to indicate how keys of that Map-valued property are to be
serialized.

To associate serializer to use for Map keys of specific type you need
to register key serializer using Modules: `SimpleModule` has method
`addKeySerializer()` (as well as `addKeyDeserializer()`). You need to
use these.

But even registration worked, this woudn't:

>                 jsonGenerator.writeStartObject();
>                 jsonGenerator.writeNumberField("itemId", 
> basketItem.getItemId());
>                 jsonGenerator.writeStringField("itemName", 
> basketItem.getItemName());
>                 jsonGenerator.writeObjectField("unitPrice", 
> basketItem.getUnitPrice());
>                 jsonGenerator.writeEndObject();

Since keys in JSON must be Strings. So only write method allowed for
key serializers is `writeFieldName()`.

Custom key serializers are needed for types other than:

* String / CharSequence
* `Integer` / `Long`
* java.util.Date / java.util.Calendar
* java.lang.Class
* java.util.UUID
* `byte[]` (Base64 encoded String)

One possible future improvement could be allowing use of `@JsonValue`
if Class has that: I will file a github issue. But until then you may
need to add custom serializer.

-+ Tatu +-

-- 
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