Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@JsonSubTypes.Type names are neglected, only the first name is emitted #796

Open
andrewbents opened this issue Feb 11, 2022 · 2 comments · May be fixed by #798
Open

@JsonSubTypes.Type names are neglected, only the first name is emitted #796

andrewbents opened this issue Feb 11, 2022 · 2 comments · May be fixed by #798

Comments

@andrewbents
Copy link

Jackson supports specifying names for subtypes, so the following is possible

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "type",
        visible = true
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = LongDto.class, names = {"Price", "Duration"}),
        @JsonSubTypes.Type(value = BoolDto.class, names = {"Official", "Signer"}),
})
static class AbstractDto {
    public String type;
}

static class LongDto extends AbstractDto {
    public long value;

    @Override
    public String toString() {
        return "LongDto{" +
                "type='" + type + '\'' +
                ", value=" + value +
                '}';
    }
}

static class BoolDto extends AbstractDto {
    public boolean value;

    @Override public String toString() {
        return "BoolDto{" +
                "type='" + type + '\'' +
                ", value=" + value +
                '}';
    }
}

@Test
void test() throws JsonProcessingException {
    LongDto priceDto = new LongDto();
    priceDto.type = "Price";
    priceDto.value = 100;
    LongDto durationDto = new LongDto();
    durationDto.type = "Duration";
    durationDto.value = 2;

    BoolDto boolDto = new BoolDto();
    boolDto.type = "Official";
    boolDto.value = true;

    ObjectMapper objectMapper = new ObjectMapper();
    String jsonString = objectMapper.writeValueAsString(List.of(priceDto, boolDto, durationDto));
    System.out.println(jsonString); // [{"type":"Price","value":100},{"type":"Official","value":true},{"type":"Duration","value":2}]
    System.out.println(objectMapper.readValue(jsonString, new TypeReference<List<AbstractDto>>() { }));  // [LongDto{type='Price', value=100}, BoolDto{type='Official', value=true}, LongDto{type='Duration', value=2}]
}

I would expect the generator to emit something like this:

export interface AbstractDto {
  'type': 'Price' | 'Duration' | 'Official' | 'Signer';
}

export interface BoolDto extends AbstractDto {
  type: 'Official' | 'Signer';
  value: boolean;
}

export interface LongDto extends AbstractDto {
  type: 'Price' | 'Duration'';
  value: number;
}

export type AbstractDtoUnion = BoolDto | LongDto;

But the actual output is like this (only first name is taken of each type):

export interface AbstractDto {
  type: 'Official' | 'Price';
}

export interface BoolDto extends AbstractDto {
  type: 'Official';
  value: boolean;
}

export interface LongDto extends AbstractDto {
  type: 'Price';
  value: number;
}

export type AbstractDtoUnion = LongDto | BoolDto;

is it possible to support this case?

@andrewbents andrewbents linked a pull request Feb 13, 2022 that will close this issue
@Yidna
Copy link

Yidna commented Jul 6, 2022

Likely related to #794
I was running into this issue as well and rolled the version back - it no longer (incorrectly) performs a string breakdown based on the names and goes back to ignoring the annotation and using the field's type, which is technically more correct

@durgasatti
Copy link

make sure you have a .java script for estimating the errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants