eclipse-ee4j / eclipse-ee4j/yasson

@JsonbTypeAdapter is not applied for unmarshalling when @JsonbCreator is used

Open
#231 3 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
Java
Stars
218
Forks
109
Avg merge
1d 5h
Merged PRs (30d)
9

Description

Suppose we have a following enum type
```java
public static enum EnumType {
ONE("one"),
TWO("two");

private EnumType(String value) {
this.value = value;
}

private final String value;

public String getValue() {
return value;
}

public static EnumType of(String value) {
for (EnumType t : EnumType.values()) {
if (t.value.equals(value)) {
return t;
}
}
return null;
}
}
```
Then, let's define a custom JsonbAdapter for a list of EnumTypes:
```java
public class EnumTypeListAdapter implements JsonbAdapter, JsonArray> {

@Override
public JsonArray adaptToJson(List obj) {
System.out.println("I am marshalling the list of EnumTypes to JsonArray");
return Json.createArrayBuilder(obj.stream()
.map(EnumType::getValue)
.collect(Collectors.toList()))
.build();
}

@Override
public List adaptFromJson(JsonArray obj) {
System.out.println("I am unmarshalling the list of EnumTypes from JsonArray");
List enums = new ArrayList<>();
for (JsonString s : obj.getValuesAs(JsonString.class)) {
enums.add(EnumType.of(s.getString()));
}
return enums;
}
}
```
Then for the type defined as:
```java
public class CollectionAdapterType {

@JsonbTypeAdapter(EnumTypeListAdapter.class)
private List enums;

public CollectionAdapterType() {
}

public CollectionAdapterType(List enums) {
this.enums = enums;
}

public List getEnums() {
return enums;
}

public void setEnums(List enums) {
this.enums = enums;
}
}
```
the following test passes:
```java
public class CollectionAdapterTypeTest {

@Test
public void test() {
CollectionAdapterType coll = new CollectionAdapterType(asList(EnumType.ONE, EnumType.TWO));

Jsonb jsonb = JsonbBuilder.create();
String result = jsonb.toJson(coll);

assertEquals("{\"enums\":[\"one\",\"two\"]}", result);
CollectionAdapterType unmarshalled = jsonb.fromJson(result, CollectionAdapterType.class);
assertEquals(coll.getEnums(), unmarshalled.getEnums());
// passes as the custom type adapter has been called for both marshalling and unmarshalling
}
}
```
However, when we define the type with @JsonbCreator, such as:
```java
public class CollectionAdapterCreatorType {

@JsonbTypeAdapter(EnumTypeListAdapter.class)
private List enums;

private CollectionAdapterCreatorType(List enums) {
this.enums = enums;
}

@JsonbCreator
public static CollectionAdapterCreatorType create(@JsonbProperty("enums") List enums) {
return new CollectionAdapterCreatorType(enums);
}

public List getEnums() {
return enums;
}

public void setEnums(List enums) {
this.enums = enums;
}
}
```
then the following test fails:
```java
public class CollectionAdapterCreatorTypeTest {

@Test
public void test() {
CollectionAdapterCreatorType coll = CollectionAdapterCreatorType.create(asList(EnumType.ONE, EnumType.TWO));

Jsonb jsonb = JsonbBuilder.create();
String result = jsonb.toJson(coll);

assertEquals("{\"enums\":[\"one\",\"two\"]}", result);
CollectionAdapterCreatorType unmarshalled = jsonb.fromJson(result, CollectionAdapterCreatorType.class);
assertEquals(coll.getEnums(), unmarshalled.getEnums());
// custom adapter was called only for marshalling
}
}
```
The reason is that the EnumTypeListAdapter was used only when marshalling (and the CollectionAdapterCreatorType type is marshalled correctly), however, it was not picked up when unmarshalling, causing the failure.

Note: I have used Yasson 1.0.3.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the failure in CollectionAdapterCreatorTypeTest using JsonbBuilder.fromJson and compare it with CollectionAdapterTypeTest. Trace how @JsonbCreator and @JsonbTypeAdapter are processed during unmarshalling; done means EnumTypeListAdapter is called and the creator-based type round-trips with the expected enum list.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.