使用 Jackson 反序列化时禁用标量到字符串的转换

Kas*_*hna 6 java json numeric jackson spring-boot

我想识别通过请求的请求正文发送的 JSON 中不带引号(作为字符串)插入的数值POST

例如,这将是错误的 JSON 格式,因为 age 字段不包含引号:

{
  "Student":{
    "Name": "John",
    "Age":  12
  }
}
Run Code Online (Sandbox Code Playgroud)

正确的 JSON 格式是:

{
  "Student":{ 
    "Name": "John",
    "Age":  "12"
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的代码中,我将age字段的数据类型定义为 a String,因此"12"应该是正确的输入。但是,即使12使用,也不会抛出错误消息。

似乎杰克逊会自动将数值转换为字符串。如何识别数值并返回消息?

这是我迄今为止尝试识别这些数值的方法:

public List<Student> getMultiple(StudentDTO Student) {
    if(Student.getAge().getClass()==String.class) {
        System.out.println("Age entered correctly as String");
    } else{
        System.out.println("Please insert age value inside inverted commas");
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,"Please insert age value inside inverted commas"当不带引号插入年龄时,这不会打印到控制台。

小智 2

默认情况下,当目标字段为类型时,Jackson 会将标量值转换为字符串String。这个想法是为String类型创建一个自定义反序列化器并注释掉转换部分:

package jackson.deserializer;

import java.io.IOException;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;


public class CustomStringDeserializer extends StringDeserializer 
{

    public final static CustomStringDeserializer instance = new CustomStringDeserializer();

    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        if (p.hasToken(JsonToken.VALUE_STRING)) {
            return p.getText();
        }
        JsonToken t = p.getCurrentToken();
        // [databind#381]
        if (t == JsonToken.START_ARRAY) {
            return _deserializeFromArray(p, ctxt);
        }
        // need to gracefully handle byte[] data, as base64
        if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
            Object ob = p.getEmbeddedObject();
            if (ob == null) {
                return null;
            }
            if (ob instanceof byte[]) {
                return ctxt.getBase64Variant().encode((byte[]) ob, false);
            }
            // otherwise, try conversion using toString()...
            return ob.toString();
        }
        // allow coercions for other scalar types
        // 17-Jan-2018, tatu: Related to [databind#1853] avoid FIELD_NAME by ensuring it's
        //   "real" scalar
        /*if (t.isScalarValue()) {
            String text = p.getValueAsString();
            if (text != null) {
                return text;
            }
        }*/
        return (String) ctxt.handleUnexpectedToken(_valueClass, p);
    }

}
Run Code Online (Sandbox Code Playgroud)

现在注册这个解串器:

@Bean
public Module customStringDeserializer() {
    SimpleModule module = new SimpleModule();
    module.addDeserializer(String.class, CustomStringDeserializer.instance);
    return module;
}
Run Code Online (Sandbox Code Playgroud)

当发送整数并且需要字符串时,错误如下:

{“timestamp”:“2019-04-24T15:15:58.968+0000”,“status”:400,“error”:“错误请求”,“message”:“JSON解析错误:无法反序列化 VALUE_NUMBER_INT 中的 java.lang.String实例令牌;嵌套异常为 com.fasterxml.jackson.databind.exc.MismatchedInputException:无法java.lang.String反序列化 [来源:(PushbackInputStream);行:3,列:13] 处的 VALUE_NUMBER_INT 令牌\n 的实例(通过引用链:org. hello.model.Student[\"age\"])","path":"/hello/echo"}