Skip to content

Instantly share code, notes, and snippets.

@ShahOdin
Created June 16, 2021 20:32
Show Gist options
  • Save ShahOdin/e30f0f019cdf6ce9e38e7e7537ea5cd9 to your computer and use it in GitHub Desktop.
Save ShahOdin/e30f0f019cdf6ce9e38e7e7537ea5cd9 to your computer and use it in GitHub Desktop.
deep merge but respect arrays
private def extractNestedArray(
json: Json
): Option[(NonEmptyList[String], Vector[Json])] = {
def extractNestedArrayInternal(
acum: List[String],
json: Json
): Option[(NonEmptyList[String], Vector[Json])] =
json.arrayOrObject(
or = None,
jsonArray = jsons => NonEmptyList.fromList(acum).map(_ -> jsons),
jsonObject = _.toList.headOption.flatMap {
case (k, v) =>
extractNestedArrayInternal(k :: acum, v)
}
)
extractNestedArrayInternal(Nil, json).map {
case (keys, jsons) =>
keys.reverse -> jsons
}
}
private def concatArrayValueAtPath(
json: Json,
path: NonEmptyList[String],
newValues: Vector[Json]
): Option[Json] =
path
.foldLeft[ACursor](
json.hcursor
) {
case (cursor, fieldName) =>
cursor.downField(fieldName)
}
.withFocusM(
_.asArray
.map(_.appendedAll(newValues))
.map(Json.fromValues)
)
.flatMap(_.top)
implicit class jsonOps(json: Json) {
def deepMergeAndConcatArrays(that: Json): Json =
extractNestedArray(that)
.flatMap {
case (arrayPath, those) =>
concatArrayValueAtPath(
json = json,
path = arrayPath,
newValues = those
)
}
.getOrElse(
json.deepMerge(that)
)
}
@ShahOdin
Copy link
Author

extracted from https://gist.github.com/ShahOdin/cb16b6989ffc382d9962075fa7dba243 where I was trying to unflatten a json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment