简体   繁体   English

Spring将CustomObject扔到控制器中的JSON

[英]Spring throw CustomObject to JSON in controller

I'm wanting to return/throw an object depending on some logic inside the controller. 我想根据控制器内部的某些逻辑返回/抛出一个对象。

For example lets say something required a user to login I'd want to return an appropriate message 例如,假设需要用户登录的内容我想返回一条适当的消息

throw a new ReturnLoginMessage("Must login", "xx@xx.com", 111)

I can't just throw ReturnLoginMessage as it'd just return the following: 我不能只抛出ReturnLoginMessage,因为它只会返回以下内容:

"exception": "com.userapi.returntypes.ReturnLoginMessage"

Which is not useful at all! 这根本没有用! I'd want the JSON representation of that returnloginmessage object. 我想要该returnloginmessage对象的JSON表示形式。

{
"message": "Must login", 
"email": "xx@xx.com", 
"code": "111"
}

Is this possible given the following controller? 给定以下控制器是否可行? What this controller does is check to see if the user already exists, if it does, they must login (which is why I'm returning the returnloginmessage object. 该控制器的作用是检查用户是否已经存在,如果存在,则必须登录 (这就是为什么我返回returnloginmessage对象的原因。

@RequestMapping(value="login/email", method=RequestMethod.POST,  produces = {MediaType.APPLICATION_JSON_VALUE })
UserCredential login(@RequestBody UserFacebookLoginContext body) throws IOException, InvalidKeySpecException,
            NoSuchAlgorithmException, ConfirmLogin, ClassNotFoundException, ConfirmResponse, InvalidRequestException, ConfirmLoginEmail {

... Logic that checks to see if user exists....
if (user does exist) 
    throw  new ReturnLoginMessage("Must login", "xx@xx.com", 111); // THis returns "exception": "com.userapi.returntypes.ReturnLoginMessage"
else if(other condition)
    throw new OtherMessage("...", "...");
else 
    return UserCredential;

Is there away I can return a JSON representation of the ReturnLoginMessage ? 是否可以返回ReturnLoginMessage的JSON表示形式 Given the following Java object? 给定以下Java对象?

public class ReturnLoginMessage extends Exception {
    private int code;
    private String message;
    private String email;
    private Date timestamp;

    public ReturnLoginMessage(int code, String message) {
        this.code = code;
        this.email = email;
        this.timestamp = new Date();
    }

    public ReturnLoginMessage(String message, int code, String email) {
        super(message);
        this.code = code;
        this.email = email;
        this.timestamp = new Date();
    }

    ... Getters .... Setters ...
}

You could achieve this by declaring a new ExceptionHandler method for ReturnLoginMessage.class . 您可以通过为ReturnLoginMessage.class声明新的ExceptionHandler方法来ReturnLoginMessage.class See this answer. 看到这个答案。

Other approach would be to extend the return value of the login to something more generic. 另一种方法是将login的返回值扩展到更通用的名称。 For example: 例如:

  1. Declare it return Object instead of UserCredentials and simply return ReturnLoginMessage instead of throwing it. 声明它返回Object而不是UserCredentials ,只返回ReturnLoginMessage而不是将其抛出。

  2. Declare it return Map<String,Object> and construct the proper key/value pairs for both scenarios. 声明它返回Map<String,Object>并为两种情况构造适当的键/值对。 See this answer 看到这个答案

I acheived almost same thing(perhaps) by this way 我通过这种方式实现了几乎相同的事情(也许)

first 第一

add a ExceptionHandler at your REST Controller and return your exception as a JSON (put a @ResponseBody). 在您的REST控制器上添加ExceptionHandler,然后将您的异常作为JSON返回(使用@ResponseBody)。

@Controller
@RequestMapping("/rest")
public class RestfulTodoController {

    @ExceptionHandler(ReturnLoginMessage.class)
    @ResponseBody
    public ReturnLoginMessage handleException(final ReturnLoginMessage e) {
        return e;
    }
    // and your login handler method

}

check whether response is Json and also returning type is ReturnLoginMessage at advice that extends AbstractMappingJacksonResponseBodyAdvice, if response is ReturnLoginMessage then modify response as you like 在扩展AbstractMappingJacksonResponseBodyAdvice的通知中检查响应是否为Json,返回类型是否为ReturnLoginMessage,如果响应为ReturnLoginMessage,则根据需要修改响应

@ControllerAdvice
public class MyResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {

    @Override
    public boolean supports(final MethodParameter returnType,
            final Class<? extends HttpMessageConverter<?>> converterType) {
        return super.supports(returnType, converterType)
                && null != returnType.getMethodAnnotation(ResponseBody.class);
    }

    @Override
    protected void beforeBodyWriteInternal(final MappingJacksonValue bodyContainer, final MediaType contentType,
            final MethodParameter returnType, final ServerHttpRequest request, final ServerHttpResponse response) {
            if (bodyContainer.getValue() instanceof ReturnLoginMessage) {
                //set some object as you like 
                bodyContainer.setValue();
            }
        }
    }

}

finally 最后

register above your advice as a Bean 在您的建议上方注册为Bean

@Configuration
public class WebAppConfiguration {

    @Bean
    public MyResponseBodyAdvice myResponseBodyAdvice() {
        return new MyResponseBodyAdvice();
    }

}

Use Fasterxml Jackson library best JSON parser for Java 使用Fasterxml Jackson库Java最佳JSON解析器
Fasterxml Jackson convert Java Collection directly into JSON. Fasterxml Jackson将Java Collection直接转换为JSON。

Maven Dependency Maven依赖

  <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${faster-xml-version}</version>
  </dependency>
  <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${faster-xml-version}</version>
   </dependency>
   <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${faster-xml-version}</version>
  </dependency>

Controller Code 控制器代码

@RequestMapping(value="login/email", method=RequestMethod.POST,               produces = {MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
 Map<String, Object> login(@RequestBody UserFacebookLoginContext body)   throws IOException, InvalidKeySpecException,
        NoSuchAlgorithmException, ConfirmLogin,    
 ClassNotFoundException, ConfirmResponse, InvalidRequestException, 
 ConfirmLoginEmail {
  ... Logic that checks to see if user exists....
if (user does exist) 
   return Utility.getSuccessResponse("message","Must    
login","email","xx@xx.com","code",111);

 else if(other condition)
 return Utility.getSuccessResponse("", "");
  else 
 return Utility.getSuccessResponse("userCredential", UserCredential);

Utility Class 实用类

 public class Utility {

public static Map<String, Object> getSuccessResponse(Object... responseContent) {

    if (responseContent.length % 2 != 0) {
        throw new IllegalArgumentException();
    }
    Map<String, Object> responseObject = new HashMap<String, Object>();
    Map<String, Object> responseList = new HashMap<String, Object>();

    for (int i = 0; i < responseContent.length; i = i + 2) {
        responseList.put(responseContent[i].toString(), responseContent[i + 1]);
    }
    responseObject.put("result", responseList);
    return responseObject;
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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