java 防止Spring自动将json中的数字字符串转换为Double

ctrmrzij  于 2023-09-29  发布在  Java
关注(0)|答案(3)|浏览(197)

我有一个POST端点在请求体中接收json,并Map到Map<String, Object>
值可以是任何字符串格式,我可以让Spring自动将"true""false"转换为Boolean"123"转换为Integer。但是我不喜欢它将"123.456"转换为Double,我希望它保持原样(String)。
有没有什么方法(最好是在application.yml中配置)可以选择性地阻止Spring将json中的数字字符串自动转换为Double

zxlwwiss

zxlwwiss1#

最简单的解决方案可能是将其更改为Map<String,String>,并在您想要的位置进行转换。我知道你对布尔值没意见,但是在这里,对于所有的选项,回到基态,重新引入想要的选项,可能比排除单个选项更好。

5jdjgkvh

5jdjgkvh2#

您可以使用注解@JsonDeserialize forJackson。
下面是一个示例模型类,它 Package 了payload Map<String,Object>字段和一个控制器类以及JSON反序列化类,并使用逻辑来完成您想要的内容:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import za.co.twentysevenfour.excel.model.converter.ObjectMapDeserializer;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class TestPayloadWrapper implements Serializable {
    private static final long serialVersionUID = 1L;

    @JsonDeserialize(using = ObjectMapDeserializer.class)
    private Map<String, Object> payload = new HashMap<>();

    public TestPayloadWrapper() {}

    public Map<String, Object> getPayload() {
        return payload;
    }

    public void setPayload(Map<String, Object> payload) {
        this.payload = payload;
    }
}

控制器类别:

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import za.co.twentysevenfour.excel.model.jpa.TestPayloadWrapper;
    
import java.util.Map;
        
        
@RestController
public class PayloadController {
    @RequestMapping(value = "/postEndpoint", method = RequestMethod.POST)
    public Map<String, Object> postEndpoint(@RequestBody TestPayloadWrapper payload) 
    {
        return payload.getPayload();
    }
}

JsonDeserializer类:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

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

public class ObjectMapDeserializer extends JsonDeserializer<Map<String,Object>> {

    @Override
    public Map<String,Object> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        Map<String,Object> result = new HashMap<>();
        ObjectNode objectNode = jsonParser.readValueAsTree();
        objectNode.fieldNames().forEachRemaining(field -> {
            JsonNode fieldValue = objectNode.get(field);
            if(fieldValue.isBoolean()) {
                result.put(field,fieldValue.asBoolean());
            } else if(fieldValue.isInt()) {
                result.put(field,fieldValue.asInt());
            } else if(fieldValue.isLong()) {
                result.put(field,fieldValue.asLong());
            } else if(fieldValue.isDouble()) {
                // Here you set the double as a string
                result.put(field,fieldValue.asText());
            } else {
                result.put(field,fieldValue.asText());
            }
        });
        return result;
    }
}

这不是最漂亮的解决方案,这是我知道的唯一一个,我猜你需要扩展和修改一些类型化器类来满足所有的值类型,但至少这给了你一个如何为特定字段做它的坚实示例,我测试了这个,它工作。
然而,我建议你总是知道你将收到的值的类型,但我完全理解会有某些情况下,这可能不是这样。
我使用的测试json payload如下:

{
    "payload" : { "testDouble" : 1.40 }
}
nbewdwxp

nbewdwxp3#

我不会为你的情况建议下面的细节。因为你只需要禁用“123.56”或类似的自动转换,但保持像它是为其他人。因为下面的属性对所有。
spring.Jackson.mapper.allow-coercion-of-scalars=false
我不认为他们是一个特定的配置在属性文件。如果有,也请让我知道。我能建议的是创建一个自定义配置,为ObjectMapper创建一个bean,并为序列化创建一个自定义模块,它可以做到不覆盖其他配置。
它可能看起来像:

@Configuration public class JacksonConfiguration {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();

        // Create a module for custom serialization
        SimpleModule module = new SimpleModule();
        module.addSerializer(Double.class, ToStringSerializer.instance);
        objectMapper.registerModule(module);

        return objectMapper;
    }
}

或者你可以做一个简单的想法。只要把所有东西都当作String,然后通过解析手动转换。如果你只有几个字段,你可以使用这个想法。😄

相关问题