Spring Boot - Different model representations / Mu

2019-08-02 11:59发布

my backend must offer two different APIs - different access to the same models, respectively, same implementation and same mappings to the database. Models are send as JSONs and they are consumed by the backend in the same way.

But different JSON representations are necessary on each API. F.e. I'd like to name some fields differently (w/ @JsonProperty f.e.) or want to omit some.

As mentioned, they should be consumed by the controllers in the same way they are produced.

Since only the representation differs: is there a simple and DRY compliant way to accomplish this?

Example to this:

Calling

ProductsController.java

    sym/products/1

should return

{
  "id": 1,
  "title": "stuff",
  "label": "junk"
}

and calling

ProductsController.java

    frontend/products/1

should return

{
  "id": 1,
  "label": "junk",
  "description": "oxmox",
  "even-more": "text"
}

Thanks a lot!

Tim

2条回答
爷、活的狠高调
2楼-- · 2019-08-02 12:47

Separate DTOs may be the best solution.

An alternate (assuming you are using Jackson) is to have one DTO with the all the different fields, and then use MixIns to control how the DTO is serialized.

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {

    public static void main(String[] args) throws Exception  {

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.addMixIn(SomeDTOWithLabel.class, IgnoreLabelMixin.class);

        SomeDTOWithLabel dto = new SomeDTOWithLabel();
        dto.setLabel("Hello World");
        dto.setOtherProperty("Other property");
        String json = objectMapper.writeValueAsString(dto);
        System.out.println("json = " + json);
    }

    public static class SomeDTOWithLabel {
        private String label;
        private String otherProperty;

        public String getOtherProperty() {
            return otherProperty;
        }

        public void setOtherProperty(String otherProperty) {
            this.otherProperty = otherProperty;
        }

        public String getLabel() {
            return label;
        }
        public void setLabel(String label) {
            this.label = label;
        }
    }

    public abstract class IgnoreLabelMixin {
        @JsonIgnore
        public abstract String getLabel();

    }
}

For instance we have DTOs with deprecated properties that old clients may still depend on, but we don't want to send them to newer client, so we use MixIns to supress them.

查看更多
Root(大扎)
3楼-- · 2019-08-02 12:47

If this is simply a case of returning a lightweight payload depending on which path you call, you can configure your json serializer (ObjectMapper) to omit empty fields. Then in your service only select and populate the subset of fields you wish to return.

    objectMapper.setSerializationInclusion(Include.NON_NULL); // omits null fields

However, if you wish to return differently named fields, use a different API model.

查看更多
登录 后发表回答