我想在序列化期间将一个字段注入响应对象。是否可以将“ success”:“ true”注入到JSON响应对象中?对于所有已序列化的父响应对象,这应该是一个通用解决方案。
例如对象:
public class UserResponse {
private int id;
private String firstName;
private String lastName;
private Organisation organisation;
// getters setters
}
杰克逊应该返回:
{
"success": "true",
"id": 1,
"firstName": "tom",
"lastName": "jeffrey",
"organisation": {
// etc.
}
}
我已经尝试过
public class CustomJsonSerializer extends StdSerializer<Object> {
public CustomJsonSerializer() {
this(null);
}
public CustomJsonSerializer(Class<Object> t) {
super(t);
}
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("success", "true");
jsonGenerator.writeObject(o);
jsonGenerator.writeEndObject();
}
}
但没有成功:
Could not write JSON: Can not start an object, expecting field name (context: Object); nested exception is com.fasterxml.jackson.core.JsonGenerationException: Can not start an object, expecting field name (context: Object)
答案 0 :(得分:1)
我想您需要的是
@JsonAppend(attrs = {@JsonAppend.Attr(value = "success")})
public class UserResponse implements Serializable {
private int id;
private String firstName;
private String lastName;
private Organisation organisation;
// getters setters
}
您调查过吗?
这是我认为会完成的示例。
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.annotation.JsonAppend;
import org.junit.Assert;
import org.junit.Test;
import java.io.Serializable;
public class InjectFieldTest {
@Test
public void testResponse() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
final UserResponse response =
new UserResponse(1, "Stack", "Overfloww", new Organisation("Developers"));
final ObjectWriter writer =
mapper.writerFor(UserResponse.class).withAttribute("success", "true");
final String out = writer.writeValueAsString(response);
System.out.println("jsData = " + out);
Assert.assertTrue(out.contains("success"));
}
@JsonAppend(attrs = {@JsonAppend.Attr(value = "success")})
private class UserResponse implements Serializable {
private int id;
private String firstName;
private String lastName;
private Organisation organisation;
public UserResponse(int id, String firstName, String lastName, Organisation organisation) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.organisation = organisation;
}
public int getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Organisation getOrganisation() {
return organisation;
}
}
private class Organisation {
private String name;
public Organisation(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
根据您的成功标准,可以将此值设置为true或false。
答案 1 :(得分:1)
在序列化为JSON之前,可以使用ResponseBodyAdvice
来修改控制器返回的对象。这是一个简单的示例,默认情况下将其应用于所有响应:
控制器返回的视图
public class Greeting {
private static final String message = "Hello World!";
public String getMessage() {
return message;
}
}
用于设置状态的响应包装器
public class ResponseWrapper {
private Object data;
private boolean success;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
}
控制器
@RestController
@RequestMapping("/api/hello")
public class HelloController {
@GetMapping
public Greeting hello() {
return new Greeting();
}
}
验证行为的测试
@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest
public class HelloControllerTest {
@Autowired
private MockMvc mockMvc;
private static final String GREETING_ENDPOINT = "/api/hello";
@Test
public void returnsGreetingWithStatus() throws Exception {
mockMvc.perform(get(GREETING_ENDPOINT))
.andExpect(jsonPath("$.data.message").value("Hello World!"))
.andExpect(jsonPath("$.success").value(true));
}
}
ResponseBodyAdvice
@ControllerAdvice
public class ResponseStatusAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return converterType.equals(MappingJackson2HttpMessageConverter.class);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
ResponseWrapper wrapper = new ResponseWrapper();
wrapper.setData(body);
wrapper.setSuccess(true);
return wrapper;
}
}
这应该给您一个良好的开端。 附带一提,您始终可以利用HTTP状态代码。它是协议的一部分,将始终进行设置。
答案 2 :(得分:1)
我不知道是否可以在serialization
期间完成此操作。但是,如果需要,您可以稍微修改Response
来以通用方式实现所需的功能:
public class ServiceResponse <T>{
private boolean success;
//your data which you want to access/use in client side. You can pass `UserResponse` or whatever class you want to pass as general.
private T data;
}
现在,将值设置为此class
对象和serialize
。您可以根据需要添加message
字符串字段用于自定义消息。
现在,ServiceResponse
也将接受其他classes
。
答案 3 :(得分:0)
将布尔成功添加到UserResponse类,并在序列化之前进行设置。