更改Swagger在Java中生成JSON响应的方式

时间:2018-04-18 08:38:52

标签: java json spring rest swagger

我使用Swagger设置REST Api服务。为此,我使用了以下版本:

swagger(YAML) - 文件版本2.0
swagger codegen cli version v2.3.0
springfox版本2.5.0

API服务的任务是响应我们存储在数据库中的数据及其关系。 但是,我们的数据中存在循环关系。这意味着每个对象a可以与对象b具有关系,对象b可以与对象a具有向后关系。

现在使用Swagger,这将生成无穷无尽的长JSON,从而导致错误。 代码如下所示:

public class Service extends DataObject {

   @SerializedName("provides")
   private List<Utility> provides;

   /**
    * Get provides
    *
    * @return provides
    **/
   @ApiModelProperty(required = true, value = "")
   public List<Utility> getProvides() {
       return provides;
   }
}

public class Utility extends DataObject {
   @SerializedName("providedBy")
   private List<Service> providedBy;

   /**
    * Get providedBy
    *
    * @return providedBy
    **/
   @ApiModelProperty(required = true, value = "")
   public List<Service> getProvidedBy() {
       return providedBy;
   }
}

然后在回复中:

@Override
public ResponseEntity<List<Service>> servicesGet(
        @Min(0) @ApiParam(value = "The number of layers of relations the object is enriched by. Lower numbers typically increase performance.", defaultValue = "0") @Valid @RequestParam(value = "layersOfRelations", required = false, defaultValue = "0") final Integer layersOfRelations) {
    String accept = this.request.getHeader("Accept");
        List<Service> services = Util.getServices();
        return new ResponseEntity<List<Service>>(services, HttpStatus.OK);
}

我的问题是,在哪里以及如何更改方法servicesGet()中为返回自动生成的输出?
我不想将整个对象b转换为JSON,而只将其转换为标题,这样就不会有无限的递归。

1 个答案:

答案 0 :(得分:0)

因此经过一些研究后我发现,那个招摇使用Jackson将对象转换为JSON(即使生成的代码中包含的@SerializedName参数来自gson库,至少在我的情况下如此)。

这意味着在这种情况下,我可以简单地使用杰克逊提供的自定义技术,它就像一个魅力。 我只需编写自定义Jackson适配器注释:

@SerializedName("provides")
@JsonSerialize(using = DataObjectAdapter.class)
private List<Utility> provides;

并且适配器看起来像这样:

public static class DataObjectAdapter extends JsonSerializer<List<Utility>> {

    @Override
    public void serialize(final List<Utility> arg0, final JsonGenerator arg1, final SerializerProvider arg2)
            throws IOException {
        arg1.writeStartArray();
        for (Utility object : arg0) {
            arg1.writeStartObject();
            arg1.writeStringField("id", object.getId());
            arg1.writeStringField("title", object.getTitle());
            arg1.writeStringField("description", object.getDescription());
            arg1.writeEndObject();
        }
        arg1.writeEndArray();
    }

}

所以现在不是将整个对象写入JSON(因此递归地将所有子对象添加到其中),他只会将我在适配器中描述的信息写入JSON。

类似地,我在JSON中读出ID并将其映射到我的数据的反序列化器看起来像这样

public static class ServiceDeserializer extends StdDeserializer<Service> {

    public ServiceDeserializer() {
        super(Service.class);
    }

    @Override
    public Service deserialize(final JsonParser jp, final DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        List<Utility> objects = Util.getUtilities();
        JsonNode node = jp.getCodec().readTree(jp);
        String id = node.get("id").asText();
        String title = node.get("title").asText();
        String description = node.get("description").asText();
        Service service = new Service(id, title, description);
        for (JsonNode utility : node.get("provides")) {
            String checkId = utility.get("id").asText();
            for (DataObject object : objects) {
                if (object.getId().equals(checkId)) {
                    service.addUtility(object);
                    break;
                }
            }
        }
        return service;
    }
}