public static <T> T decode(String json, Class<T> valueType) throws IOException {
return OBJECT_MAPPER.readValue(json, valueType);
}
public static void main(String[] args) throws IOException {
String jsonStr = "{\"number\":2233445566.77}";
System.out.println(JsonUtils.decode(jsonStr, Map.class));
}
我传入的值为 json = {“number” : 2233445566.77}, valueType = Map.class
默认输出为:{number=2.23344556677E9}
我需要的输出为:{number=2233445566.77}
跟一下源码
ObjectMapper.java
public <T> T readValue(String content, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType));
}
protected Object _readMapAndClose(JsonParser p0, JavaType valueType)
throws IOException
{
try (JsonParser p = p0) {
Object result;
JsonToken t = _initForReading(p, valueType);
final DeserializationConfig cfg = getDeserializationConfig();
final DeserializationContext ctxt = createDeserializationContext(p, cfg);
if (t == JsonToken.VALUE_NULL) {
// Ask JsonDeserializer what 'null value' to use:
result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else {
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
} else {
// 这里是反序列化的地方
result = deser.deserialize(p, ctxt);
}
ctxt.checkUnresolvedObjectId();
}
if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
_verifyNoTrailingTokens(p, ctxt, valueType);
}
return result;
}
}
MapDeserializer.java
public Map<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
if (_propertyBasedCreator != null) {
return _deserializeUsingCreator(p, ctxt);
}
if (_delegateDeserializer != null) {
return (Map<Object,Object>) _valueInstantiator.createUsingDelegate(ctxt,
_delegateDeserializer.deserialize(p, ctxt));
}
if (!_hasDefaultCreator) {
return (Map<Object,Object> ) ctxt.handleMissingInstantiator(getMapClass(),
getValueInstantiator(), p,
"no default constructor found");
}
// Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
JsonToken t = p.getCurrentToken();
if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) {
// (empty) String may be ok however; or single-String-arg ctor
if (t == JsonToken.VALUE_STRING) {
return (Map<Object,Object>) _valueInstantiator.createFromString(ctxt, p.getText());
}
// slightly redundant (since String was passed above), but also handles empty array case:
return _deserializeFromEmpty(p, ctxt);
}
final Map<Object,Object> result = (Map<Object,Object>) _valueInstantiator.createUsingDefault(ctxt);
if (_standardStringKey) {
// 跟到这里
_readAndBindStringKeyMap(p, ctxt, result);
return result;
}
_readAndBind(p, ctxt, result);
return result;
}
protected final void _readAndBindStringKeyMap(JsonParser p, DeserializationContext ctxt,
Map<Object,Object> result) throws IOException
{
final JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
MapReferringAccumulator referringAccumulator = null;
boolean useObjectId = (valueDes.getObjectIdReader() != null);
if (useObjectId) {
referringAccumulator = new MapReferringAccumulator(_containerType.getContentType().getRawClass(), result);
}
String key;
if (p.isExpectedStartObjectToken()) {
key = p.nextFieldName();
} else {
JsonToken t = p.getCurrentToken();
if (t == JsonToken.END_OBJECT) {
return;
}
if (t != JsonToken.FIELD_NAME) {
ctxt.reportWrongTokenException(this, JsonToken.FIELD_NAME, null);
}
key = p.getCurrentName();
}
for (; key != null; key = p.nextFieldName()) {
JsonToken t = p.nextToken();
if (_ignorableProperties != null && _ignorableProperties.contains(key)) {
p.skipChildren();
continue;
}
try {
// Note: must handle null explicitly here; value deserializers won't
Object value;
if (t == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = _nullProvider.getNullValue(ctxt);
} else if (typeDeser == null) {
// 跟到这里
value = valueDes.deserialize(p, ctxt);
} else {
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
if (useObjectId) {
referringAccumulator.put(key, value);
} else {
result.put(key, value);
}
} catch (UnresolvedForwardReference reference) {
handleUnresolvedReference(ctxt, referringAccumulator, key, reference);
} catch (Exception e) {
wrapAndThrow(e, result, key);
}
}
// 23-Mar-2015, tatu: TODO: verify we got END_OBJECT?
}
UntypedObjectDeserializer.java
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
switch (p.getCurrentTokenId()) {
case JsonTokenId.ID_START_OBJECT:
{
JsonToken t = p.nextToken();
if (t == JsonToken.END_OBJECT) {
return new LinkedHashMap<String,Object>(2);
}
}
case JsonTokenId.ID_FIELD_NAME:
return mapObject(p, ctxt);
case JsonTokenId.ID_START_ARRAY:
{
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) { // and empty one too
if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return NO_OBJECTS;
}
return new ArrayList<Object>(2);
}
}
if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return mapArrayToArray(p, ctxt);
}
return mapArray(p, ctxt);
case JsonTokenId.ID_EMBEDDED_OBJECT:
return p.getEmbeddedObject();
case JsonTokenId.ID_STRING:
return p.getText();
case JsonTokenId.ID_NUMBER_INT:
if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
return _coerceIntegral(p, ctxt);
}
return p.getNumberValue(); // should be optimal, whatever it is
// 代码走到了这里
case JsonTokenId.ID_NUMBER_FLOAT:
// 如果开启了DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS,就回返回一个DecimalValue
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return p.getDecimalValue();
}
// 否则返回NumberValue
return p.getNumberValue();
case JsonTokenId.ID_TRUE:
return Boolean.TRUE;
case JsonTokenId.ID_FALSE:
return Boolean.FALSE;
case JsonTokenId.ID_END_OBJECT:
// 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME),
// if caller has advanced to the first token of Object, but for empty Object
return new LinkedHashMap<String,Object>(2);
case JsonTokenId.ID_NULL: // 08-Nov-2016, tatu: yes, occurs
return null;
//case JsonTokenId.ID_END_ARRAY: // invalid
default:
}
return ctxt.handleUnexpectedToken(Object.class, p);
}
/**
* Feature that determines whether JSON floating point numbers
* are to be deserialized into {@link java.math.BigDecimal}s
* if only generic type description (either {@link Object} or
* {@link Number}, or within untyped {@link java.util.Map}
* or {@link java.util.Collection} context) is available.
* If enabled such values will be deserialized as {@link java.math.BigDecimal}s;
* if disabled, will be deserialized as {@link Double}s.
* <p>
* Feature is disabled by default, meaning that "untyped" floating
* point numbers will by default be deserialized as {@link Double}s
* (choice is for performance reason -- BigDecimals are slower than
* Doubles).
*/
// 默认是false
USE_BIG_DECIMAL_FOR_FLOATS(false),
要想把科学计数法转成非科学计数法展示,需要将此配置开启
开启方法:
public static ObjectMapper getObjectMapper() {
ObjectMapper om = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
om.registerModule(javaTimeModule);
// 此处是开启USE_BIG_DECIMAL_FOR_FLOATS
om.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
return om;
}