FasterXML / FasterXML/jackson-databind

Polymorphic subtype deduction behaves differently based on order of fields

Abierto
#3,183 11 comentarios 2 reacciones 0 asignados Ver en GitHub
polymorphic-deduction
Lenguaje dominante
Java
Estrellas
3.7k
Forks
1.5k
Merge medio
3 d 6 h
PR fusionados (30 d)
28

Descripción

**Describe the bug**
I'm using @JsonTypeInfo(use = Id.DEDUCTION) and have created a scenario where the mapper behaves differently depending on how I order my fields, which I think should be undesirable behavior.

**Version information**
2.12.3

**To Reproduce**
JUnit 5 test:

```
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.json.JsonMapper;

public class DeductionBasedPolymorphismFieldOrderTest {

@Test
public void test1() throws JsonMappingException, JsonProcessingException {
String json = "{\"kingdom\":\"animal\",\"woof\": \"woof.wav\",\"meow\": \"meow.wav\",\"arf\": \"arf.wav\",\"bark\": \"bark.wav\"}";
Animal animal = new JsonMapper().readValue(json, Animal.class); // Succeeds!
assertTrue(animal.getClass().getName().contains("CatDog"));
}

@Test
public void test2() throws JsonMappingException, JsonProcessingException {
String json = "{\"kingdom\":\"animal\",\"meow\": \"meow.wav\",\"woof\": \"woof.wav\",\"arf\": \"arf.wav\",\"bark\": \"bark.wav\"}";
Animal animal = new JsonMapper().readValue(json, Animal.class);
// Throws: UnrecognizedPropertyException: Unrecognized field "woof" (class
// DeductionBasedPolymorphismFieldOrderTest$Cat)
assertTrue(animal.getClass().getName().contains("CatDog"));
}

@Test
public void test3() throws JsonMappingException, JsonProcessingException {
String json = "{\"kingdom\":\"animal\",\"arf\": \"arf.wav\",\"meow\": \"meow.wav\",\"woof\": \"woof.wav\",\"bark\": \"bark.wav\"}";
Animal animal = new JsonMapper().readValue(json, Animal.class);
// Throws: UnrecognizedPropertyException: Unrecognized field "meow" (class
// DeductionBasedPolymorphismFieldOrderTest$Dog2)
assertTrue(animal.getClass().getName().contains("CatDog"));
}

@JsonTypeInfo(use = Id.DEDUCTION, defaultImpl = CatDog.class)
@JsonSubTypes({ @JsonSubTypes.Type(value = Cat.class), @JsonSubTypes.Type(value = Dog1.class),
@JsonSubTypes.Type(value = Dog2.class) })
public static class Animal {
public String kingdom;
}

public static class Cat extends Animal {
public String meow;
}

public static class Dog1 extends Animal {
public String woof;
public String bark;
}

public static class Dog2 extends Animal {
public String woof;
public String arf;
}

public static class CatDog extends Animal {
public String meow;
public String woof;
public String bark;
public String arf;
}
}
```

**Expected behavior**
This situation should always trigger the use of defaultImpl as it does in test 1, or, failing that, throw an InvalidTypeIdException referencing "Cannot deduce unique subtype" (but the behavior should be the same across examples).

**Additional context**
The order of fields should not be what decides subtyping, as it is unintuitive and cannot always be controlled for.

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.