You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot配置:将特定格式字符串转换为JavaMoney字段

解决Spring Boot中把自定义格式货币字符串转成JavaMoney的问题

这个场景我之前帮同事处理过,核心就是搞定Jackson的反序列化逻辑+JavaMoney的配置,一步步来就行:

1. 先添加必要的依赖

首先得引入JavaMoney的API、参考实现,还有Jackson专门处理JavaMoney的模块,不然Spring Boot没法识别Money类型的序列化/反序列化。

Maven 依赖(pom.xml)

<!-- JavaMoney API 核心包 -->
<dependency>
    <groupId>org.javamoney</groupId>
    <artifactId>moneta-api</artifactId>
    <version>1.4.2</version>
</dependency>
<!-- JavaMoney 官方参考实现 -->
<dependency>
    <groupId>org.javamoney</groupId>
    <artifactId>moneta</artifactId>
    <version>1.4.2</version>
    <classifier>all</classifier>
</dependency>
<!-- Jackson 适配JavaMoney的模块 -->
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-money</artifactId>
    <version>2.15.2</version>
</dependency>

Gradle 依赖(build.gradle)

implementation 'org.javamoney:moneta-api:1.4.2'
implementation 'org.javamoney:moneta:1.4.2:all'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-money:2.15.2'

2. 处理自定义数字格式的反序列化

你收到的"12.323,44"是欧洲风格数字格式(千分位用.,小数点用,),默认的Jackson Money模块识别不了,所以需要自定义反序列化逻辑。

方式一:给实体字段加注解(局部生效)

先写一个自定义反序列化器:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.javamoney.moneta.Money;
import javax.money.Monetary;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.Locale;

public class EuroStyleMoneyDeserializer extends StdDeserializer<Money> {

    // 用德国Locale适配千分位.、小数点,的格式,欧洲多数国家通用
    private static final NumberFormat EURO_NUMBER_FORMAT = NumberFormat.getNumberInstance(Locale.GERMAN);

    protected EuroStyleMoneyDeserializer() {
        super(Money.class);
    }

    @Override
    public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String amountStr = p.getText();
        try {
            // 解析字符串为数字
            Number parsedNumber = EURO_NUMBER_FORMAT.parse(amountStr);
            // 这里默认用EUR作为货币代码,若需动态切换可调整逻辑(比如从请求参数取)
            return Money.of(parsedNumber.doubleValue(), Monetary.getCurrency("EUR"));
        } catch (Exception e) {
            throw new IOException("解析货币字符串失败: " + amountStr, e);
        }
    }
}

然后在你的实体类字段上指定这个反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.javamoney.moneta.Money;

public class MyObject {
    private Long id;
    
    @JsonDeserialize(using = EuroStyleMoneyDeserializer.class)
    private Money amount;

    // 记得生成getter、setter、构造方法
}

方式二:全局配置Jackson(推荐,所有Money字段生效)

如果不想每个实体都加注解,直接全局配置ObjectMapper:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.money.MoneyModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonMoneyConfig {

    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.build();
        // 注册Jackson的JavaMoney模块
        objectMapper.registerModule(new MoneyModule());
        // 替换Money类型的默认反序列化器为自定义实现
        objectMapper.configOverride(Money.class)
                .setDeserializer(com.fasterxml.jackson.databind.deser.BeanDeserializerModifier.modifyDeserializer(
                        objectMapper.getDeserializationConfig(),
                        Money.class,
                        new EuroStyleMoneyDeserializer()
                ));
        return objectMapper;
    }
}

3. 关键注意点

  • 货币代码:上面默认用了EUR,如果你需要支持多货币,可以把货币代码作为请求的额外字段,或者在配置里设置默认货币。
  • 精度问题:用doubleValue()可能有精度损失,追求高精度的话可以转成BigDecimal处理:
    BigDecimal amountBigDecimal = new BigDecimal(parsedNumber.toString());
    return Money.of(amountBigDecimal, Monetary.getCurrency("EUR"));
    
  • Locale适配:如果你的输入格式对应其他地区,只需要替换Locale.GERMAN为对应Locale即可(比如法国、意大利的Locale也支持这种格式)。

配置完成后,Spring Boot就能自动把{"id": 1, "amount": "12.323,44"}转换成MyObject实例,其中amount字段就是Money类型的EUR 12323.44。

内容的提问来源于stack exchange,提问作者Fabio Ebner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:44:40