简体   繁体   中英

Return JSON with key-value pair

I use this code to generate response from REST endpoint:

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));
        }

Object:

@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;
    }

    ......
}

Now I get this response:

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

I need to change it like this:

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

Is there someway to archive his without added a lot of "" symbols?

The " symbols are quotes, and they are necessary as part of the JSON specification. As for why your JSON is in a format you don't want, it has to do with your code here (and also in your corresponding StringResponseDTO ):

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

You are adding strings to a list. What you want is to create a list of objects, instead. Each object would contain a property and string value.

What you have proposed is not valid JSON:

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

What you need is this format instead (notice the object { symbols):

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

The format you expressed in the "wanted" result isn't valid.
What you can do is use Jackson (or GSON, depending on the library you're using) classes, for example

(Note, objectMapper is an instance of ObjectMapper )

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;
    }
}

That will be serialized to

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

Or, if you prefer, the usual Map<String, String> solution.

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;
    }
}

Which will output the same thing

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

It's up to you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM