Skip to content

Cannot serialize YAML with Deduction-Based Polymorphism #404

@phaumer

Description

@phaumer

I am not able to serialize objects that contain an interface for sub-classes using @JsonTypeInfo(use = Id.DEDUCTION). It works fine for JSON and reading YAML, but when I try to serialize the objects into a Yaml file I get an exception:

com.fasterxml.jackson.databind.JsonMappingException: Can not write a field name, expecting a value (through reference chain: jackson.MainDoc["profiles"]-]java.util.ArrayList[0]-]jackson.Profile["settings"]-]jackson.Setting1["application"])
 at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:402)
 at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:361)
 at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316)
 at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:782)
 at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeWithType(BeanSerializerBase.java:657)
 at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:735)
 at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774)
 at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)

I created a sample repo that shows the problem here: https://github.com/phaumer/jackson-yaml-deduction

I am working on a configuration file for our product that manages an array of profiles and depending of the type of the profile it would use a different settings object with different properties and sub-objects. The basic structure looks like this

name: doc1
profiles:
  - name: profile1
    type: type1
    settings:
      application: sam
      command: test
  - name: profile2
    type: type2
    settings:
      mappings: map1

The settings object is declared as

@JsonTypeInfo(use = Id.DEDUCTION)
@JsonSubTypes({ @Type(value = Setting1.class, name = "settings"),
                @Type(value = Setting2.class, name = "settings") })
public interface Setting { }

with two implementation classes for the two types of settings.

In the sample repo you see three test cases. The first one reads a sample file as json and writes it back without issues. The second one reads the yaml from above without problems, but throws the exception above when serializing it back with mapper.writeValue().

    @Test
    void testReadWriteYAML() throws Exception {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());

        File inputFile = Paths.get(inputYamlFilepath).toFile();
        MainDoc doc = mapper.readValue(inputFile, MainDoc.class);
        assertNotNull(doc);
        assertEquals(createTestObject(), doc);

        File outFile = Paths.get(outputYamlFilepath).toFile();
        mapper.writeValue(outFile, doc);
    }

The third example constructions the content as Java objects and can be serialized as json, but not yaml again.

Metadata

Metadata

Assignees

No one assigned

    Labels

    has-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issueyamlIssue related to YAML format backend

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions