返回具有键值对的JSON

时间:2019-04-02 20:52:44

标签: java

我使用以下代码从REST端点生成响应:

if (result.hasErrors()) {
            List<String> errorsList = new ArrayList<>();
            List<FieldError> errors = result.getFieldErrors();
            for (FieldError error : errors ) {
                System.out.println("Validation error in field: " + error.getObjectName() 
                               + "! Validation error message: " + error.getDefaultMessage() 
                               + "! Rejected value:" + error.getRejectedValue());
                errorsList.add(error.getField() + ": " + error.getDefaultMessage());
            }

            return ResponseEntity.ok(new StringResponseDTO(errorsList));
        }

对象:

@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
@JsonTypeName("response")
public class StringResponseDTO {

    private String redirect;

    private List<String> errors;

    public StringResponseDTO(String redirect) {
        super();
        this.redirect = redirect;
    }

    public StringResponseDTO(List<String> errors) {
        this.errors = errors;
    }

    ......
}

现在,我收到此回复:

{
  "response" : {
    "errors" : [ "expiration_year: must not be null", "default_transaction_type: must not be null"]
  }
}

我需要这样更改它:

{
      "response" : {
        "errors" : [ "expiration_year": "must not be null", "default_transaction_type": "must not be null"]
      }
    }

是否可以在不添加大量“”符号的情况下将其存档?

2 个答案:

答案 0 :(得分:1)

"符号是引号,它们是JSON规范的一部分是必需的。至于为什么您的JSON是不需要的格式,它与这里的代码(以及与您相应的StringResponseDTO中的代码)有关:

errorsList.add(error.getField() + ": " + error.getDefaultMessage());

您正在将字符串添加到列表中。您想要的是创建一个对象列表。每个对象都将包含一个属性和字符串值。

您提出的建议无效的JSON:

{
  "response" : {
  "errors" : [ "expiration_year": "must not be null", "default_transaction_type": "must not be null"]
      }
}

您需要的是这种格式(请注意对象{符号):

{
   "response" : {
   "errors" : [ {"expiration_year": "must not be null"}, {"default_transaction_type": "must not be null"}]
      }
}

答案 1 :(得分:1)

您在“所需”结果中表示的格式无效。
您可以做的是使用Jackson类(或GSON,具体取决于您使用的库),例如

(请注意,objectMapperObjectMapper的实例)

public class StringResponseDTO {
    private String redirect;
    private TreeNode errors;

    public StringResponseDTO(final String redirect) {
        this.redirect = redirect;
    }

    public StringResponseDTO(final Collection<? extends FieldError> errors) {
        this.errors =
                errors.stream()
                      .collect(Collector.of(
                              objectMapper::createObjectNode,
                              (json, e) -> json.put(e.getField(), e.getDefaultMessage()),
                              (json, toMerge) -> {
                                  json.setAll(toMerge);
                                  return json;
                              }
                      ));
    }

    public String getRedirect() {
        return redirect;
    }

    public TreeNode getErrors() {
        return errors;
    }
}

它将被序列化为

{
    "redirect": "...",
    "errors": {
        "field1": "err field1",
        "field2": "err field2",
        "field3": "err field3"
    }
}

或者,如果愿意,可以使用常规的Map<String, String>解决方案。

public class StringResponseDTO {
    private String redirect;
    private Map<String, String> errors;

    public StringResponseDTO(final String redirect) {
        this.redirect = redirect;
    }

    public StringResponseDTO(final Collection<? extends FieldError> errors) {
        this.errors =
                errors.stream()
                      .collect(Collectors.toMap(
                              FieldError::getField,
                              FieldError::getDefaultMessage
                      ));
    }

    public String getRedirect() {
        return redirect;
    }

    public Map<String, String> getErrors() {
        return errors;
    }
}

哪个会输出相同的东西

{
    "redirect": "...",
    "errors": {
        "field1": "err field1",
        "field2": "err field2",
        "field3": "err field3"
    }
}

由您决定。