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

如何用Chimney将Scala嵌套样例类转换为含新增字段的类

问题与解决方案:Scala嵌套样例类转换(Chimney库)

问题背景

需要将package a下的嵌套样例类转换为package b下的结构,两者大部分字段一致,仅目标类b.InternalMyClientSettings多了一个需用常量填充的company字段。尝试使用Scalaland Chimney的into和transformInfo方法,未解决缺失字段的转换问题。

原类结构(package a)

package a

import scala.concurrent.duration.{Duration, FiniteDuration}

final case class mySettings(multicache: myCacheSetting, defaultTtlHours: Duration)

final case class myCacheSetting(
    weightedRoundrobin: InternalWRRMultiCacheSetting,
    attempts: Int,
    clusters: Seq[MyClusterSetting]
)

final case class MyClusterSetting(id: String, settings: InternalMyClientSettings)

final case class InternalMyClientSettings(
    user: String,
    environment: Option[InternalMyClientEnvironmentSettings]
)

final case class InternalMyClientEnvironmentSettings(
    socketTimeout: Option[FiniteDuration],
    connectTimeout: Option[FiniteDuration]
)

final case class InternalWRRMultiCacheSetting(maxWeight: Int, incrementWeight: Int, decrementWeight: Int)

目标类结构(package b)

package b

import scala.concurrent.duration.{Duration, FiniteDuration}

final case class mySettings(multicache: myCacheSetting, defaultTtlHours: Duration)

final case class myCacheSetting(
    weightedRoundrobin: InternalWRRMultiCacheSetting,
    attempts: Int,
    clusters: Seq[MyClusterSetting]
)

final case class MyClusterSetting(id: String, settings: InternalMyClientSettings)

final case class InternalMyClientSettings(
    user: String,
    company: String,
    environment: Option[InternalMyClientEnvironmentSettings]
)

final case class InternalMyClientEnvironmentSettings(
    socketTimeout: Option[FiniteDuration],
    connectTimeout: Option[FiniteDuration]
)

final case class InternalWRRMultiCacheSetting(maxWeight: Int, incrementWeight: Int, decrementWeight: Int)

解决方案

1. 基础依赖导入

确保项目已引入Chimney库(以sbt为例):

libraryDependencies += "io.scalaland" %% "chimney" % "0.8.0" // 替换为最新稳定版本

导入核心转换器:

import io.scalaland.chimney.dsl._

2. 两种实现方式

方式一:单次转换直接填充字段

在转换链中精准定位到嵌套层级,用withFieldConst给新增的company字段赋值:

val sourceSettings: a.mySettings = // 你的源实例
val targetSettings: b.mySettings = sourceSettings
  .into[b.mySettings]
  .withFieldComputed(_.multicache.clusters, clusters =>
    clusters.map(cluster =>
      cluster.into[b.MyClusterSetting]
        .withFieldConst(_.settings.company, "你的常量值") // 替换为实际常量
        .transform
    )
  )
  .transform

方式二:定义复用的隐式转换器

如果需要重复使用转换逻辑,为嵌套类定义隐式转换器,Chimney会自动在顶层转换时应用:

import io.scalaland.chimney.Transformer

// 定义a.InternalMyClientSettings到b.InternalMyClientSettings的隐式转换器
implicit val clientSettingsTransformer: Transformer[a.InternalMyClientSettings, b.InternalMyClientSettings] =
  Transformer.define[a.InternalMyClientSettings, b.InternalMyClientSettings]
    .withFieldConst(_.company, "你的常量值") // 替换为实际常量
    .build

// 顶层转换自动处理所有嵌套结构
val targetSettings: b.mySettings = sourceSettings.into[b.mySettings].transform

思路说明

  • Chimney默认自动匹配同名同类型字段,但目标类新增字段时,必须显式提供填充逻辑。
  • 方式一适合一次性转换,直接在转换链中处理嵌套层级的字段;方式二更适合需要多次复用转换逻辑的场景,通过隐式转换器简化顶层调用。
  • 核心是定位到新增字段所在的嵌套层级:mySettings → myCacheSetting → Seq[MyClusterSetting] → InternalMyClientSettings,确保赋值逻辑作用在正确的层级上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:52:48