Il existe une API qui renvoie JSON avec une propriété de type objet s'il existe une valeur et un type de tableau s'il est vide, et par défaut les types ne correspondent pas et ne peuvent pas être liés à la classe.
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `net.yotama.sample.resource.Resource$Member` out of START_ARRAY token
at [Source: (String)"{"member": []}"; line: 1, column: 12](through reference chain: net.yotama.sample.resource.Resource["member"])
Utilisez `` JsonDeserializer '' de Jackson et remplacez-le par null quand il s'agit d'un tableau afin qu'il puisse être lié à une classe de ressources.
S'il y a une valeur
{
"member": {
"name": "yotama"
}
}
S'il n'y a pas de valeur
{
"member": []
}
Resource.java
package net.yotama.sample.resource;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Value;
import java.io.IOException;
@Value
public class Resource {
@JsonDeserialize(using = MemberDeserializer.class)
Member member;
@Value
public static class Member {
String name;
}
public static class MemberDeserializer extends JsonDeserializer<Member> {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public Member deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
TreeNode treeNode = p.getCodec().readTree(p);
return treeNode.isObject() ? objectMapper.readValue(treeNode.toString(), Member.class) : null;
}
}
}
lombok.config
#J'utilise Lombok pour plus de simplicité,
# 1.16.Utilisé par Jackson à partir de 20@ConstructorProperties ne sera pas affecté, donc définissez-le provisoirement
lombok.anyConstructor.addConstructorProperties=true
package net.yotama.sample.resource;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(Theories.class)
public class ResourceTest {
private ObjectMapper objectMapper = new ObjectMapper();
@DataPoints
public static Fixture[] data = {
new Fixture("{\"member\": []}", new Resource(null)),
new Fixture("{\"member\": null}", new Resource(null)),
new Fixture("{\"member\": {\"name\": \"hoge\"}}", new Resource(new Resource.Member("hoge"))),
};
@Theory
public void test(Fixture fixture) throws IOException {
assertThat(objectMapper.readValue(fixture.json, Resource.class), is(fixture.expected));
}
@RequiredArgsConstructor
public static class Fixture {
final String json;
final Resource expected;
}
}