Hallo, und vielen Dank für all die Bemühungen, die Sie in die Migration von Circe und Scala 3 investieren.
Ich habe versucht, den Aufwand zu messen, der erforderlich ist, um eines meiner Projekte auf Scala3 zu migrieren.
Ich habe ein bisschen Probleme mit der JSON-Serialisierung, da es Snake_case-Transformationen für Fallklassenattribute beinhaltet.
Früher habe ich circe-generic-extras mit ConfiguredJsonObject verwendet, aber ich habe gesehen, dass es wahrscheinlich nicht so bald auf Scala3 aktualisiert wird, was ich verstehen kann.
Gibt es eine andere Möglichkeit (außer dem Schreiben eines Encoders von Hand), um einen Encoder zu erhalten, der snake_case für Fallklassenattribute verwendet?
Wie einen Encoder abzuleiten und ihn irgendwie "zuzuordnen"?
Es tut mir leid, wenn die Frage nicht klar genug ist, aber ich versuche, eine Problemumgehung dafür zu finden, und nochmals vielen Dank für Ihre Zeit und Mühe.
Sie könnten mapJson
für ein abgeleitetes Encoder
und eine Snake_case-Transformation für jeden Schlüssel in diesem Json
Objekt ausführen.
Richtig, ich denke, leider ist Ihre beste Wahl für Scala 3 derzeit so etwas (getestet auf Scala 3):
scala> import io.circe.{Encoder, JsonObject}, io.circe.generic.semiauto.deriveEncoder
scala> import java.util.regex.Pattern
scala> val snakeCaseTransformation: String => String = s => {
| val basePattern: Pattern = Pattern.compile("([A-Z]+)([A-Z][a-z])")
| val swapPattern: Pattern = Pattern.compile("([a-z\\d])([A-Z])")
| val partial = basePattern.matcher(s).replaceAll("$1_$2")
| swapPattern.matcher(partial).replaceAll("$1_$2").toLowerCase
| }
val snakeCaseTransformation: String => String = Lambda$6404/700040865<strong i="6">@2b523359</strong>
scala> def snakeCaseIfy[A](encoder: Encoder.AsObject[A]): Encoder.AsObject[A] =
| encoder.mapJsonObject(obj =>
| JsonObject.fromIterable(obj.toIterable.map {
| case (k, v) => (snakeCaseTransformation(k), v) }
| )
| )
|
def snakeCaseIfy
[A](encoder: io.circe.Encoder.AsObject[A]): io.circe.Encoder.AsObject[A]
scala> case class Foo(firstName: String, lastName: String)
// defined case class Foo
scala> implicit val encoderFoo: Encoder.AsObject[Foo] = snakeCaseIfy(deriveEncoder)
val encoderFoo: io.circe.Encoder.AsObject[Foo] = io.circe.Encoder$$anon$66<strong i="7">@717a0dd4</strong>
scala> import io.circe.syntax._
scala> Foo("Foo", "McBar").asJson
val res0: io.circe.Json = {
"first_name" : "Foo",
"last_name" : "McBar"
}
Super ausführliche Hilfe.
Danke schön!
Es tut mir leid, dass ich nur das Serialisierungsproblem aufgedeckt habe, obwohl ich offensichtlich Deserialisierungsprobleme habe.
Gibt es eine Möglichkeit, mit einem abgeleitetenDecoder "unsakify" zu machen?
Edit: https://gitter.im/circe/circe?at=5d542e282612bb718c685031 dieses withFocus
scheint ein guter Ausgangspunkt für meine Nachforschungen zu sein.
Etwas um diese Zeilen:
private val snakePattern = "_([a-z\\d])".r
private val snakeToCamel: String => String = s => {
snakePattern.replaceAllIn(s, {m =>
m.group(1).toUpperCase()
})
}
private def unSnakeCaseIfy(o: JsonObject): JsonObject =
JsonObject.fromIterable(o.toVector.map {
case (k, v) => snakeToCamel(k) -> v
})
def unSnakeCaseIfy[A](decoder: Decoder[A]): Decoder[A] = (c: HCursor) => {
decoder.tryDecode(c.withFocus(_.mapObject(unSnakeCaseIfy)))
}
Hilfreichster Kommentar
Richtig, ich denke, leider ist Ihre beste Wahl für Scala 3 derzeit so etwas (getestet auf Scala 3):