Press "Enter" to skip to content

JSON序列化导致Long类型被搞成Integer

背景:

昨天在调试接口的时候总是报错,服务的截图错误信息为: java.lang.Integer cannot be cast to java.lang.Long

分析:

我写的是一个通用服务,接受数据的时候,jackson框架将json里面的对象数据用Map<String,Object>来接,我们也知道json是没有long类型的概念的,比如我传入的数据:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"value1": "12345",
"value2": 67890
}
{ "value1": "12345", "value2": 67890 }
{
  "value1": "12345", 
  "value2": 67890
}

尽管我java类原本认为value2是Long类型,但是跑到json里面之后,他就只能变成这种不带引号的数值。

反解析成java对象之后,可能这个Long类型就丢了。

解决:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class CustomDeserializer extends JsonDeserializer<Object> {
private final UntypedObjectDeserializer delegate;
public CustomDeserializer() {
this.delegate = new UntypedObjectDeserializer(null, null);
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Object m = delegate.deserialize(p, ctxt);
return recursivelyProcessValue(m);
}
private Object recursivelyProcessValue(Object value) {
if (value instanceof Map) {
Map<String, Object> map = (Map<String, Object>) value;
for (Map.Entry<String, Object> entry : map.entrySet()) {
entry.setValue(recursivelyProcessValue(entry.getValue()));
}
} else if (value instanceof List) {
List<Object> list = (List<Object>) value;
for (int i = 0; i < list.size(); i++) {
list.set(i, recursivelyProcessValue(list.get(i)));
}
} else if (value instanceof String) {
String strValue = (String) value;
if (strValue.startsWith("@JSON_TYPE_LONG:")) {
Long longValue = Long.parseLong(strValue.substring("@JSON_TYPE_LONG:".length()));
return longValue;
}
}
return value;
}
}
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; import java.io.IOException; import java.util.List; import java.util.Map; public class CustomDeserializer extends JsonDeserializer<Object> { private final UntypedObjectDeserializer delegate; public CustomDeserializer() { this.delegate = new UntypedObjectDeserializer(null, null); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Object m = delegate.deserialize(p, ctxt); return recursivelyProcessValue(m); } private Object recursivelyProcessValue(Object value) { if (value instanceof Map) { Map<String, Object> map = (Map<String, Object>) value; for (Map.Entry<String, Object> entry : map.entrySet()) { entry.setValue(recursivelyProcessValue(entry.getValue())); } } else if (value instanceof List) { List<Object> list = (List<Object>) value; for (int i = 0; i < list.size(); i++) { list.set(i, recursivelyProcessValue(list.get(i))); } } else if (value instanceof String) { String strValue = (String) value; if (strValue.startsWith("@JSON_TYPE_LONG:")) { Long longValue = Long.parseLong(strValue.substring("@JSON_TYPE_LONG:".length())); return longValue; } } return value; } }
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class CustomDeserializer extends JsonDeserializer<Object> {
    private final UntypedObjectDeserializer delegate;

    public CustomDeserializer() {
        this.delegate = new UntypedObjectDeserializer(null, null);
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Object m = delegate.deserialize(p, ctxt);
        return recursivelyProcessValue(m);
    }

    private Object recursivelyProcessValue(Object value) {
        if (value instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) value;
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                entry.setValue(recursivelyProcessValue(entry.getValue()));
            }
        } else if (value instanceof List) {
            List<Object> list = (List<Object>) value;
            for (int i = 0; i < list.size(); i++) {
                list.set(i, recursivelyProcessValue(list.get(i)));
            }
        } else if (value instanceof String) {
            String strValue = (String) value;
            if (strValue.startsWith("@JSON_TYPE_LONG:")) {
                Long longValue = Long.parseLong(strValue.substring("@JSON_TYPE_LONG:".length()));
                return longValue;
            }
        }
        return value;
    }
}

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Object.class, new CustomDeserializer ());
objectMapper.registerModule(module);
return objectMapper;
}
}
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(Object.class, new CustomDeserializer ()); objectMapper.registerModule(module); return objectMapper; } }
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Object.class, new CustomDeserializer ());
        objectMapper.registerModule(module);
        return objectMapper;
    }
}

这样我们只需要将long类型的字段的值写成格式类似:”@JSON_TYPE_LONG:12345″ 的形式就行了。

或者为了稳妥起见,你可以将Jackson框架转换过后的对象根据你的需要将他用recursivelyProcessValue函数处理一下就行了,这个函数会递归找值满足条件的进行修改。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注