alibaba / fastjson

FASTJSON 2.0.x has been released, faster and more secure, recommend you upgrade.
https://github.com/alibaba/fastjson2/wiki/fastjson_1_upgrade_cn
Apache License 2.0
25.74k stars 6.5k forks source link

JSONField偶尔失效 #2788

Open hsgmj opened 5 years ago

hsgmj commented 5 years ago

各位大神您好,这个问题困扰几天了一直没找到办法。

就是A服务上面我定义了一个ModelVO 里面加了 @JSONField(name="序列号")等,希望的是 最终结果如下(对应的json属性变成中文),但是会发现偶尔是中文 偶尔是英文,然后发现一个规律。如果json解析发现这个对象是linkedHashMap的时候 就是英文,如果是发现是ModelVo的时候就是中文(实际上我这个A服务的确每次都代码里面存进去的都是VO实体对象),麻烦有知道的看看怎么解决,我放在vo的属性文件也不行 放在get也是一样。

{ "data": { "产品类型": "iPhone6,2", "产地": "iPhone 5s", "序列号": "DX6R5VW1FR9M", "支持网络": [ "https://www.apple.com/iphone/LTE/", "https://support.apple.com/HT202909" ], "网络型号,若与本机不一致,则可能为翻新机": "A1530" }, "errorCode": "", "errorMsg": "", "success": true }

package com.fastboot.fmd.checkcoverage.api.vo.apple;

import com.alibaba.fastjson.annotation.JSONField; import org.codehaus.jackson.annotate.JsonIgnoreProperties;

import java.io.Serializable;

/**

Omega-Ariston commented 5 years ago

可以提供下序列化/反序列化部分使用的函数代码吗 :)

hsgmj commented 5 years ago
  1.     //todo 这里存的vo。 当初最开始用的fastjson 但是发现因为加了jsonfild中文导致有问题 所以变相先用jackson反序列化为 VO.然后将VO对象存入 response这个结果集里面。打印这个vo对象是中文。

注意:这里是一个RPC远程服务。A 调用这个服务 返回response ,然后A那边对应有一个ResponseBodyAdvice会判断如果返回值是response则 bodyRewrite = JSONObject.toJSONString(body); 序列化,但是打印 logger.info("ResponseRewriteAdvice into Response class[{}]", object == null ? "" : object.getClass().toString()); 会发现 有时候是linkedHashMap 有时候是vo。但是服务那边打印的都是vo。

反序列化: @Override public Response serial(CommonReqParamDTO commonReqParamDTO) { Response response = new Response<>(); Map<String, String> params = new HashMap<>(1); Map<String, String> headers = new HashMap<>(1); initReqParamMap(params, headers, commonReqParamDTO); ObjectMapper objectMapper = new ObjectMapper(); StringBuffer urlBuffer = new StringBuffer(baseConfig.getFmdService().get("url")).append(Constant.ServiceCodeUrl.SERIAL.getUrl()); Response result = HttpClientUtils.doGet(urlBuffer.toString(), headers, params,Constant.CONNECT_TIMEOUT,Constant.SOCKET_TIMEOUT); if (result.isSuccess() && isSuc(result)) { ImeiVO imeiVO = objectMapper.readValue(result.getData(), ImeiVO.class); //todo 这里存的vo。 当初最开始用的fastjson 但是发现因为加了jsonfild中文导致有问题 所以变相先用jackson反序列化为 VO.然后将VO对象存入 response这个结果集里面。 response.setDataWithSuccess(imeiVO); } else { setErrorCodeWithMsg(response, objectMapper, result); }

//这里一定打印出来的都是中文 但是RPC结果解析有时候是英文有时候中文 logger.info("serial response[{}]", JSONObject.toJSONString(response));

    return response;
}

序列化: 序列化的时候 有时候是linkedHashMap 如果是这个则返回给前端的(打印的也是)都是英文。如果是vo则是中文。

hsgmj commented 5 years ago

可以提供下序列化/反序列化部分使用的函数代码吗 :)

我已经发你了 麻烦看看 A 网关,他会面向APP,都是返回的response对象。response里面可以存放实体。 然后 A 请求 B服务(RPC 用的dubbo)。 B服务将对象存入到response里面 返回【打印的时候可以看到 json对象都是中文正常 class也是对应的vo],在A中 会发现 有时候是map(map则失效显示的是非中文),vo则正常。谢谢 详细代码看我发的

如下是序列化的地方:

public class ResponseRewriteAdvice implements ResponseBodyAdvice { private static Logger logger = LoggerFactory.getLogger(ResponseRewriteAdvice.class); private static final String DATA_REMAKE = "##$$##"; private static final String DATA_REMAKE_REPLACE = "\"##$$##\"";

public ResponseRewriteAdvice() {
}

public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return true;
}

public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    response.setStatusCode(HttpStatus.OK);
    if (selectedContentType != null && "application".equalsIgnoreCase(selectedContentType.getType()) && "json".equalsIgnoreCase(selectedContentType.getSubtype())) {
        response.getHeaders().setContentType(MediaType.parseMediaType("text/json;charset=utf-8"));
    } else {
        response.getHeaders().setContentType(selectedContentType);
    }

    logger.info("ResponseRewriteAdvice into body[{}],class[{}]", JSONObject.toJSONString(body));
    String bodyRewrite;
    if (body instanceof Response) {
        Object object = ((Response)body).getData();
        logger.info("ResponseRewriteAdvice into Response class[{}]", object == null ? "" : object.getClass().toString());
        bodyRewrite = JSONObject.toJSONString(body);
kimmking commented 5 years ago

看起来你的问题是,有时候被反序列化成map了

hsgmj commented 5 years ago

看起来你的问题是,有时候被反序列化成map了

是 有时候是map 这个请问你知道原因吗?

EayonTang commented 5 years ago

你好,请问你用的是哪个版本的fastjson

hsgmj commented 5 years ago

你好,请问你用的是哪个版本的fastjson

1.2.61

EayonTang commented 5 years ago

你好,请问你用的是哪个版本的fastjson

1.2.61

你好,你的目的是需要序列化和反序列化都是中文属性吗,如果是的你尝试将@JSONField同时加在get/set方法上试试看。也可以直接加在属性上。加上之后反序列化还是用fastJSON。