Skip to content

Add MapperFeature.REQUIRE_TYPE_ID_FOR_SUBTYPES to enable/disable strict subtype Type Id handling #3853

Closed
@stevestorey

Description

@stevestorey

Describe the bug
In 2.14, if you setup @JsonTypeInfo(use = Id.NAME) then all JSON passed to readValue must include the @type information, but that's no longer true in 2.15, which will now unmarshall JSON with missing type information (as long as no other constraints fail). Although I guess it's possibly something to consider as an improvement, but personally I would like to ensure that clients must pass the type information, not least so that one cannot accidentally send the wrong JSON, but have it pass because it's close enough to the intended type.

Version information
2.15.0-rc2

To Reproduce

Unit test:

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;

public class RegressionTest {
    
    @Test
    public void testTypeRequired() throws Exception {
        ObjectMapper om = new ObjectMapper();
        DoSomethingCommand cmd = om.readValue("{\"@type\":\"do-something\"}", DoSomethingCommand.class);
        assertThat(cmd).isNotNull();
        // Prove that we can't load the command _without_ the type information
        // This assertion passes in 2.14, but fails in 2.15 as nothing is thrown and the instance
        // is unmarshalled anyway
        assertThrows(InvalidTypeIdException.class, () -> om.readValue("{}", DoSomethingCommand.class));
    }
}

@JsonTypeInfo(use = Id.NAME)
interface Command {
}

@JsonTypeName("do-something")
class DoSomethingCommand implements Command {
}

/*
 * This highlights why I think it's dangerous to accept the JSON with no type information. A
 * client might accidentally send this structure, but without the type information, which would
 * be rejected in 2.14, but with 2.15 it would be accepted (incorrectly IMHO)
 */
@JsonTypeName("do-something-else")
class DoSomethingElseCommand extends DoSomethingCommand {
}

Expected behavior

The unit test passes, as an InvalidTypeIdException is thrown when no type information is present in the incoming JSON, as was the case in 2.14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions