Azure / autorest.java

Extension for AutoRest (https://github.com/Azure/autorest) that generates Java code
MIT License
33 stars 82 forks source link

mgmt azure-json, flatten property in parent class will cause issue in child class in a different package #2742

Closed XiaofeiCao closed 3 months ago

XiaofeiCao commented 4 months ago

Parent class:

// parent class in different package
public class PirCommunityGalleryResource implements JsonSerializable<PirCommunityGalleryResource> {
    private CommunityGalleryIdentifier innerIdentifier;

    private CommunityGalleryIdentifier innerIdentifier() {
        return this.innerIdentifier;
    }

    PirCommunityGalleryResource withInnerIdentifier(CommunityGalleryIdentifier innerIdentifier) {
        this.innerIdentifier = innerIdentifier;
        return this;
    }

    public String uniqueId() {
        return this.innerIdentifier() == null ? null : this.innerIdentifier().uniqueId();
    }

    public PirCommunityGalleryResource withUniqueId(String uniqueId) {
        if (this.innerIdentifier() == null) {
            this.innerIdentifier = new CommunityGalleryIdentifier();
        }
        this.innerIdentifier().withUniqueId(uniqueId);
        return this;
    }
}

Child class:

// child class in different package
public final class CommunityGalleryInner extends PirCommunityGalleryResource {

    @Override
    public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
        jsonWriter.writeStartObject();
        // `innerIdentifier()` can't be accessed, as it is private
        jsonWriter.writeJsonField("identifier", innerIdentifier());
        return jsonWriter.writeEndObject();
    }

    public static CommunityGalleryInner fromJson(JsonReader jsonReader) throws IOException {
        return jsonReader.readObject(reader -> {
            CommunityGalleryInner deserializedCommunityGalleryInner = new CommunityGalleryInner();
            while (reader.nextToken() != JsonToken.END_OBJECT) {
                String fieldName = reader.getFieldName();
                reader.nextToken();

                if ("identifier".equals(fieldName)) {
                    // `withInnerIdentifier()` can't be accessed, as parent class is in a different package and the method is package private
                    deserializedCommunityGalleryInner.withInnerIdentifier(CommunityGalleryIdentifier.fromJson(reader));
                } else {
                    reader.skipChildren();
                }
            }

            return deserializedCommunityGalleryInner;
        });
    }
}

This is similar to the discriminator issue, which we solved by shadowing the discriminator in child class: https://github.com/Azure/autorest.java/pull/2639

We could do similar things here, though we may need to also override parent flatten properties getter and setter, e.g. in child class:

// child class in different package
public final class CommunityGalleryInner extends PirCommunityGalleryResource {
    // shadow property
    private CommunityGalleryIdentifier innerIdentifier;

    // override parent's flatten property's properties getters
    @Override
    public String uniqueId() {
        return this.innerIdentifier == null ? null : this.innerIdentifier.uniqueId();
    }

    // override parent's flatten property's properties setter
    @Override
    public PirCommunityGalleryResource withUniqueId(String uniqueId) {
        if (this.innerIdentifier == null) {
            this.innerIdentifier = new CommunityGalleryIdentifier();
        }
        this.innerIdentifier.withUniqueId(uniqueId);
        return this;
    }

    @Override
    public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
        jsonWriter.writeStartObject();
        // use shadowing property
        jsonWriter.writeJsonField("identifier", this.innerIdentifier);
        return jsonWriter.writeEndObject();
    }

    public static CommunityGalleryInner fromJson(JsonReader jsonReader) throws IOException {
        return jsonReader.readObject(reader -> {
            CommunityGalleryInner deserializedCommunityGalleryInner = new CommunityGalleryInner();
            while (reader.nextToken() != JsonToken.END_OBJECT) {
                String fieldName = reader.getFieldName();
                reader.nextToken();

                if ("identifier".equals(fieldName)) {
                    // use shadowing property
                    deserializedCommunityGalleryInner.innerIdentifier = CommunityGalleryIdentifier.fromJson(reader);
                } else {
                    reader.skipChildren();
                }
            }

            return deserializedCommunityGalleryInner;
        });
    }
}
### Tasks
- [x] shadow flattened property
- [x] override parent getter
- [x] override parent setter
- [x] toJson use shadowed property
- [x] fromJson set shadowed property