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

如何基于配置的Locale/设置格式化jOOQ查询Trino返回的数字?

问题

我用jOOQ查询Trino数据库,希望在获取org.jooq.Result<org.jooq.Record>后调用formatJSON()时,org.jooq.Field<out Number>类型的字段能按照jOOQ配置的java.util.Locale自动格式化(比如Locale.US显示2,000,Locale.GERMANY显示2.000),不需要额外编写临时格式化代码。

目前已尝试通过Settings设置各类Locale参数,但未达到预期效果。示例代码如下:

val usSettings = Settings().apply {
    locale = Locale.US
    renderLocale = Locale.US
    parseLocale = Locale.US
    interpreterLocale = Locale.US
}
val dsl = org.jooq.impl.DSL.using(trinoDataSource, SQLDialect.TRINO, usSettings)
val result = dsl
    .select(<Integer类型的Field>)
    .from(<表>)
    .fetch()
    .formatJSON()

当前返回的JSON结果中数字为原生数值:

{
  "fields": [
    {
      "schema": "the schema",
      "table": "the table",
      "name": "field name",
      "type": "INTEGER"
    }
  ],
  "records": [
    { "field name": 2000 } // 期望得到"2,000"
  ]
}

解决方案

核心原因

formatJSON()默认输出JSON原生数据类型,而JSON规范中的数字是无格式的数值,不会自动添加千分位分隔符。要实现本地化格式化,需要将数字转换为字符串类型输出。

方案1:查询阶段直接格式化字段

在查询时用jOOQ工具类或Trino原生函数将数字转成本地化字符串,formatJSON()会直接输出格式化后的结果:

val locale = Locale.US
val formatter = NumberFormat.getNumberInstance(locale)

val result = dsl
    .select(
        // 将数字字段格式化为字符串
        DSL.val(formatter.format(<Integer类型的Field>)).as(<字段名>)
    )
    .from(<表>)
    .fetch()
    .formatJSON()

如果Trino支持SQL原生格式化函数(如format_number),也可以直接调用:

val result = dsl
    .select(
        DSL.field("format_number({0}, 'N')", String::class.java, <Integer类型的Field>).as(<字段名>)
    )
    .from(<表>)
    .fetch()
    .formatJSON()

方案2:自定义FormattingProvider实现全局配置

通过实现FormattingProvider接口,覆盖JSON格式化时的数字处理逻辑,实现全局自动格式化:

class LocaleAwareFormattingProvider(private val locale: Locale) : DefaultFormattingProvider() {
    private val numberFormatter = NumberFormat.getNumberInstance(locale)

    override fun formatValue(ctx: FormatContext, value: Any?) {
        if (value is Number) {
            // 将数字格式化为字符串后输出
            ctx.format(numberFormatter.format(value))
        } else {
            // 其他类型沿用默认处理逻辑
            super.formatValue(ctx, value)
        }
    }
}

构建DSLContext时注入该自定义Provider:

val locale = Locale.US
val configuration = DefaultConfiguration()
    .set(trinoDataSource)
    .set(SQLDialect.TRINO)
    .set(Settings().apply { this.locale = locale })
    .set(LocaleAwareFormattingProvider(locale))

val dsl = DSL.using(configuration)
val result = dsl
    .select(<Integer类型的Field>)
    .from(<表>)
    .fetch()
    .formatJSON()

此方案会让所有数字类型字段自动按指定Locale格式化为字符串输出。

注意事项

  • 格式化后的数字会变为JSON字符串(带引号),若下游系统需要数值类型,此方案不适用。
  • 若要保留JSON数值类型同时显示格式化效果,只能在前端展示阶段做本地化处理,因为JSON本身不支持带格式的数值。

内容的提问来源于stack exchange,提问作者Pablo Cavalieri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:35:14