-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
[BUG] [JavaSpring] Discriminator property gets serialized twice #3796
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
Comments
Maybe it's the same bug of this issue: #2835 |
If removing discriminator property addresses the issue, we can certainly do that. |
Manually removing the attribute (plus getter/setter), corresponding to the discriminator property, from the generated class does the trick. As stated above, I've just needed to turn off the I've also tried to use I think that the |
I would like to contribute to the project, but it's my first time ever in the open-source.. |
@nickshoe I might beat you to it. |
…or JavaSpring. Fixes OpenAPITools#3796
…or JavaSpring. Fixes OpenAPITools#3796
I think I managed to solve this as part of #5120 - feel free to give it a go (although it's not a part of an existing release, it will be in openapi-generator 4.3.x release). |
@bkabrda it seems like the approach does work, but the change from PROPERTY to EXISTING_PROPERTY needs to be made for other generators as well, for example JavaSpring, which we are using. I'll created a PR for this shortly. |
This fixes issue OpenAPITools#3796 for JavaSpring. It's a very straightfoward extension of OpenAPITools#5120 for the JavaSpring generator (that PR was just for the Java generator).
I've tried to generate the same example above for "spring" target with a 4.3.x build, but still can find the discriminator property in the class. |
This fixes issue OpenAPITools#3796 for JavaSpring. It's a very straightfoward extension of OpenAPITools#5120 for the JavaSpring generator (that PR was just for the Java generator).
This fixes issue OpenAPITools#3796 for JavaSpring. It's a very straightfoward extension of OpenAPITools#5120 for the JavaSpring generator (that PR was just for the Java generator).
In version 4.3.1 (#5243) the Jackson's In fact, this leads to a Looking at the
So, the I continue to think that we only need to prevent the actual property generation in the generated class code, and keep using the Jackson's |
I had a PR open to do that, but it was significantly more complicated and invasive than the EXISTING_PROPERTY strategy. Right now I'm using my own fork of openapi-generator that has the @JsonIgnore fix instead, and have a ticket open to replace that with the latest version of openapi-generator from upstream (thus switching to the EXISTING_PROPERTY fix). |
@keenanpepper and @wing328 the fact is that the latest release broke the type serialization. |
We tried to update from 4.2.3 to 4.3.1, and I stumbled upon this issue. Our serialization is now broken, because the discriminator field is missing. Before everything worked fine. We're using this approach, which worked fine in 4.2.3. (no field generated in the java code)
With the PR that got released with 4.3.0 we now have to explicitly define the discriminator property? Is this intended? |
@bonii-xx that's exactly what I'm doing with 4.2.2 (or 4.2.3). Actually, omitting the discriminator property in the
I don't know why they accepted the IMHO explicitely defining the discriminator property is a must, because at a certain point in time an object must be serialized to JSON (or XML) and, without an additional property valued with the class name, the class information is lost. Thus the need for specifying in which key (property) expose this info (string). |
My example does not contain the discriminator property in the |
@bonii-xx the two issues are related, please read all the comments. |
Version 4.3.0 broke my clients too. The include change of When I instantiate a new object of a sub-type class, the discriminator doesn't exists in this object with the new strategy. A workaround to this is add the discriminator as property in the POJO class, but in this way the client will have to fill this property when instantiate a object. |
Please try the latest master or 5.0.0-beta3 if you've not already done so. |
unfortunately 5.0.0-beta3 has the same problem with |
Hi I have the same problem and it seems very important to me. Will it be solved in version 5.0.0? |
I have the same problems as mentioned above:
Anyway, right now i generate the code, change the code as mentioned above and commit it (which i would like to avoid). |
This might be a possible solution: #4588 (comment) |
Just wanted to share my workaround for this (not great...but it's working until this can be fixed properly). This is specifically for folks using Spring Boot 2, but I'm sure will help other Spring and even non-Spring Java project maintainers:
This assumes a fairly standard model inheritance e.g.:
|
Could use open api generator template? Change within the template. |
Any news here? It's super annoying to set all the technical values (discimininator) in the client all the time. My workaround looks like this: FooTo:
...
discriminator:
propertyName: mytype
mapping:
bar: BarTo
BarTo:
allOf:
- $ref: '#/components/schemas/FooTo'
- type: object
properties:
mytype:
type: string
enum:
- 'bar'
default: 'bar' Anyway... The clutter and annoying part just moved - from client code to specification |
One way to fix this would be to change the generated JsonTypeInfo.As.PROPERTY to JsonTypeInfo.As.EXISTING_PROPERTY inside @JsonTypeInfo:
when changed to
works as a charm and returns only one property instead of two. So the generating template of the plugin needs to be updated for certain templates. In my case this would be JavaJaxRS/typeInfoAnnotation.mustache. |
I think the changes made with #9441) removes the JsonTypeInfo.As.EXISTING_PROPERTY from model annotations mustache and replaces it with JsonTypeInfo.As.PROPERTY. I actually could not figure out the motives for this. Does anyone know the background, if not I can create a MR which works just as the previous versions for such objects. |
@amir-ba, please read this: #3796 (comment). TL;DR: |
@nickshoe thanks for clarifying this for me. |
I ultimately think that we could solve this by using the Does anyone know why This way, serialization and deserialization work without errors. If one needs to know the type of the object, then Java provides this information through classes (and reflection). @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY , property = "some_property", visible = false) Or, equivalently (omitting the @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY , property = "some_property") Or, equivalently ( @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "some_property") Please consider the example below: The super-class: package it.unibo.nickshoe;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.time.Instant;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = StartEvent.class, name = "StartEvent"),
})
public abstract class Event {
private int id;
private Instant createdAt;
public Event() {}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getCreatedAt() {
return createdAt;
}
} The sub-class: package it.unibo.nickshoe;
public class StartEvent extends Event {
private int position;
public StartEvent() {}
public void setPosition(int position) {
this.position = position;
}
public int getPosition() {
return position;
}
} The test: import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import it.unibo.nickshoe.Event;
import it.unibo.nickshoe.StartEvent;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.Instant;
public class JacksonPROPERTYStrategyTestCase {
public static final String EXPECTED_START_EVENT_JSON = "{\"type\":\"StartEvent\",\"id\":100,\"createdAt\":\"2022-07-29T21:38:00Z\",\"position\":10}";
private ObjectMapper mapper = JsonMapper.builder()
.addModule(new ParameterNamesModule())
.addModule(new Jdk8Module())
.addModule(new JavaTimeModule())
.build()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
@Test
public void testDeserialization() throws JsonProcessingException {
Event deserializedStartEvent = mapper.readValue(EXPECTED_START_EVENT_JSON, Event.class);
Assertions.assertEquals(deserializedStartEvent.getClass(), StartEvent.class);
}
@Test
public void testSerialization() throws JsonProcessingException {
StartEvent startEvent = new StartEvent();
startEvent.setId(100);
startEvent.setCreatedAt(Instant.parse("2022-07-29T21:38:00.000Z"));
startEvent.setPosition(10);
String serializedStartEvent = mapper.writeValueAsString(startEvent);
Assertions.assertEquals(serializedStartEvent, EXPECTED_START_EVENT_JSON);
}
} |
This is quite frustrating. IMO the solution needs to be to remove the discriminator property from the generated POJO altogether. The whole purpose of polymorphic types in this case is to encode the type info into the class itself. Having the discriminator property on the class just introduces the possibility that it be set such that it disagrees with the actual class of the object. |
I just noticed this was for Spring - this is an issue for the jaxrs-spec generator also. |
Was this issue solved? It is very frustrating to encounter this issue years after it was reported. |
Looks like the issue is not resolved for the latest version as well I am using and still facing the same issue. |
openapi-generator version
3.3.4
Command line used for generation
I'm working with a JHipster API-First project, which uses openapi-generator-maven-plugin (v3.3.4).
Description
By following the OpenAPI 3.x documentation/examples, it seems that the property used as discriminator must also be specified in the properties list of the schema.
Example:
The generated Java class for the code above seems to differ from the Jackson guidelines for polymorphic type handling with annotations, where the property used as discriminator must not be present in the class.
The generated code also includes this property as a class attribute with getter/setter.
This causes the serialization output to include the property twice, as shown below.
I've also tried to remove the property from the OpenAPI properties list, leaving intact the discriminator part; this way the generated code corresponds to the Jackson's guidelines and the serialization works just fine. On the other hand, I get the following error during the deserialization process.
To fix this, i've configured the Jackson
ObjectMapper
object for ignoring this kind of situations.By the way, this looks like a workaround to me beacuse my OpenAPI file doesn't (strictly) follows the spec.
Suggest a fix
The generator should not include an additional attribute (with getter/setter) for a discriminator property.
The text was updated successfully, but these errors were encountered: