The pitfalls I have recently stepped on in my work will be used for the results.Result<T>
Encapsulation, but I stepped on two big pits of FastJson and construction method. Share it, please be careful not to step on the same pit.
1. Test code
- Created
Result<String>
Object, serialized to JSON string - Deserialize JSON strings to
Result<String>
Objectpublic static void main(String[] args) { // Create an object Result<String> result = new Result<String>() .setRet(-1) .setData(null) .setError(new (404).addErrorDetail("id", 9, "")); // Serialize the object into a JSON string String resultJson = (result, , ); (resultJson); // Deserialization Result<String> resultFromJson = (resultJson, new TypeReference<Result<String>>() { }); (resultFromJson); }
Serialized JSON string
{ "data":null, "error":{ "code":404, "details":[ { "data":9, "field":"id", "msg":"" } ] }, "ret":-1 }
It has to do with the construction method.
creatorConstructor
Determined asError(int code)
This construction method, and this construction method is onlyint code
This parameter is created in deserializationWhen, that's it
code
Assignment of fields without deserializationdetails
Field.
Solution
-
Adding construction method
Error(int code, List<ErrorDetail> details)
-
Result<T>Adding the parameterless construction method
At this point, the problem is solved.
summary
- JSON deserialization is closely related to constructing methods. It is recommended that each class provide parameterless constructing methods.
- If a certain class is not designed to provide a parameterless construction method, special attention should be paid to the above two issues. It is recommended to provide a full-parameter construction method.
Related Class Definitions
Correct Result<T>
import ;
import ;
import ;
import ;
@Data
@Accessors(chain = true)
public class Result<T> {
/**
* ret >= 0 success;
* ret < 0 error;
*/
private int ret;
private T data;
private Error error;
@Data
@Accessors(chain = true)
public static class Error {
private int code;
private List<ErrorDetail> details;
public Error(int code) {
= code;
= new ArrayList<>();
}
/**
* Pay special attention to the modification of the construction method, and do not put it before the previous construction method, otherwise it will cause FastJson reverse-sequence listing problems.
* <p>
* public Error(CmnCode code) {
* = ();
* = new ArrayList<>();
* }
*/
public Error(int code, List<ErrorDetail> details) {
= code;
if (null == details) {
= new ArrayList<>();
} else {
= details;
}
}
public Error addErrorDetail(String msg) {
(new ()
.setMsg(msg));
return this;
}
public Error addErrorDetail(String field, String msg) {
(new ()
.setField(field)
.setMsg(msg));
return this;
}
public Error addErrorDetail(Object data, String msg) {
(new ()
.setData(data)
.setMsg(msg));
return this;
}
public Error addErrorDetail(String field, Object data, String msg) {
(new ()
.setField(field)
.setData(data)
.setMsg(msg));
return this;
}
}
@Data
@Accessors(chain = true)
public static class ErrorDetail {
/**
* error field;
*/
private String field;
/**
* error field value;
*/
private Object data;
/**
* error field message;
*/
private String msg;
}
}
CmnCode Enumeration
import ;
public enum CmnCode implements Serializable {
/**
* ok
*/
OK(200),
BAD_REQUEST(400),
UNAUTHORIZED(401),
FORBIDDEN(403),
NOT_FOUND(404),
METHOD_NOT_ALLOWED(405),
NOT_ACCEPTABLE(406),
CONFLICT(409),
PRECONDITION_FAILED(412),
UNSUPPORTED_MEDIA_TYPE(415),
PROTOCOL_NOT_MATCH(444),
INTERNAL_ERROR(500),
GATEWAY_ERROR(502),
SERVICE_UNAVAILABLE(503),
GATEWAY_TIMEOUT(504);
private int code;
CmnCode(int code) {
= code;
}
public static CmnCode fromHttpStatus(int httpStatus) {
for (CmnCode cmnCode : values()) {
if (() == httpStatus) {
return cmnCode;
}
}
return INTERNAL_ERROR;
}
public int getCode() {
return code;
}
public CmnCode setCode(int code) {
= code;
return this;
}
}
Result<T> that caused the problem
@Data
@Accessors(chain = true)
public class Result<T> {
/**
* ret >= 0 success;
* ret < 0 error;
*/
private int ret;
private T data;
private Error error;
@Data
@Accessors(chain = true)
public static class Error {
private int code;
private List<ErrorDetail> details;
public Error(CmnCode cmnCode) {
= ();
= new ArrayList<>();
}
public Error(int code) {
= code;
= new ArrayList<>();
}
}
}