Json4s 3.2.11与Scala2.11.6自定义JSON合并:JArray取交集实现问询
解决方案:Json4s合并JArray时取交集(替代默认并集)
你用的Json4s 3.2.11和Scala 2.11.6确实默认会把JArray合并成并集,而且MergeDep因为是包私有访问修饰符,外部代码没法直接引用或扩展,所以咱们换两个更直接的思路来实现数组取交集的需求:
方案一:针对特定字段手动处理交集后合并
如果只是某一个特定的JArray字段需要取交集,其他字段保持默认合并逻辑,这种方法最直观:
import org.json4s._ import org.json4s.native.JsonMethods._ // 定义工具函数:合并两个JSON,指定字段的数组取交集 def mergeWithSpecificArrayIntersection( left: JValue, right: JValue, targetField: String ): JValue = { // 安全提取两边的目标数组,字段不存在则返回空列表 val leftElements = (left \ targetField).extractOpt[List[JValue]].getOrElse(Nil) val rightElements = (right \ targetField).extractOpt[List[JValue]].getOrElse(Nil) // 计算数组交集(依赖JValue的结构相等性判断) val intersection = leftElements.intersect(rightElements) // 替换两边的目标字段为交集结果,再合并其他字段 val modifiedLeft = left.replace(List(targetField), JArray(intersection)) val modifiedRight = right.replace(List(targetField), JArray(intersection)) modifiedLeft merge modifiedRight } // 示例用法 val leftJson = parse("""{"items": [1,2,3], "name": "foo"}""") val rightJson = parse("""{"items": [2,3,4], "name": "bar"}""") val mergedJson = mergeWithSpecificArrayIntersection(leftJson, rightJson, "items") // mergedJson 结果:{"items": [2,3], "name": "bar"}(name字段默认取右边值)
这个方法的核心是先单独处理需要交集的数组字段,再用默认的merge逻辑处理其他字段,简单易维护。
方案二:全局自定义MergeStrategy
如果所有JArray字段都需要合并时取交集,可以自定义MergeStrategy来覆盖默认的数组合并行为:
import org.json4s._ import org.json4s.JsonAST._ import org.json4s.MergeStrategy._ // 自定义合并策略:数组取交集,其他类型用默认逻辑 val arrayIntersectionStrategy: MergeStrategy = new MergeStrategy { override def apply(parent: JValue, left: JValue, right: JValue): JValue = (left, right) match { // 匹配两个JArray,返回交集 case (JArray(leftArr), JArray(rightArr)) => JArray(leftArr.intersect(rightArr)) // 其他情况沿用默认合并逻辑(比如对象合并取并集、值覆盖等) case _ => default(parent, left, right) } } // 使用自定义策略合并JSON val leftJson = parse("""{"a": [1,2], "b": "left"}""") val rightJson = parse("""{"a": [2,3], "b": "right"}""") val mergedJson = merge(leftJson, rightJson, arrayIntersectionStrategy) // mergedJson 结果:{"a": [2], "b": "right"}
这个方案更通用,一次定义后所有数组合并都会自动取交集,适合全局需要这个规则的场景。
需要注意的是,JValue的intersect方法是基于结构相等性判断的,比如JInt(2)和JInt(2)会被判定为相等,如果你有特殊的相等判断需求,可以自己实现数组的交集逻辑(比如遍历过滤)。
内容的提问来源于stack exchange,提问作者Steven Deutscher-Kobayashi
相关产品推荐
相关产品推荐

