Сравнение ключа и значений в строке json с использованием scala

#json #scala

#json #scala

Вопрос:

Хотите сравнить первую строку json с другими 2 строками json. Сначала ключи должны совпадать. Если они совпадают, сравните вложенный ключ и значения.

  val of1 = "{"keyA":{"1":13,"0":202}}"
  val of2 = "{"keyA":{"1":12,"0":201}}"
  val of3 = "{"keyB":{"1":12}}"
  

Должно выдать ошибку из-за несоответствия ключа.

  val of1 = "{"keyA":{"1":13,"0":202}}"
  val of2 = "{"keyA":{"1":12,"0":201}}"
  val of2 = "{"keyA":{"1":11,"0":200}}"
  

Это должно возвращать true, поскольку оба ключа совпадают, а также вспомогательные ключи 1 и 0 имеют больше значений, чем вспомогательный ключ json 2 и json 3. Числа представляют собой длинные значения.

Пожалуйста, помогите.

Ниже приведена моя попытка.

  import com.fasterxml.jackson.databind.ObjectMapper
  import com.fasterxml.jackson.module.scala.DefaultScalaModule
  import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

  val of1 = "{"keyA":{"1":13,"0":202}}"
  val of2 = "{"keyA":{"1":12,"0":201}}"
  val of3 = "{"keyB":{"1":12}}"


  def OffsetComparator(json1: String, json2: String, json3:String): Boolean = {

    val mapper = new ObjectMapper() with ScalaObjectMapper
    
    mapper.registerModule(DefaultScalaModule)
    
    val jsonObj1 = mapper.readValue(json1, classOf[Map[String, Map[String, Long]]])
    val jsonObj2 = mapper.readValue(json2, classOf[Map[String, Map[String, Long]]])
    val jsonObj3 = mapper.readValue(json3, classOf[Map[String, Map[String, Long]]])


//Trying to get the key and compare first
    val mapA = jsonObj1.keySet.foreach(i=>jsonObj1.keySet(i).toString)
    val mapB = jsonObj2.keySet
    val mapC = jsonObj3.keySet



   println( (jsonObj1.keySet == jsonObj3.keySet) )

      if (mapA.keySet != mapB.keySet || mapA.keySet != mapC.keySet) throw new Exception("partitions mismatch")

      mapA.keys.forall(k => (mapA(k).asInstanceOf[Long] > mapB(k).asInstanceOf[Long] amp;amp; mapA(k).asInstanceOf[Long] > mapC(k).asInstanceOf[Long]))

// getting error :java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long when i am casting as Long.Not su

  }

  println(OffsetComparator(of1, of2,of3))
}
  

Ответ №1:

Вы можете попробовать с https://github.com/gnieh/diffson . Он доступен для circe, spray-json и play-json.

Ваш пример с Circe:

 import diffson._
import diffson.lcs._
import diffson.jsonpatch.lcsdiff._

import io.circe._
import diffson.circe._
import diffson.jsonpatch._
import io.circe.parser._

val decoder = Decoder[JsonPatch[Json]]
val encoder = Encoder[JsonPatch[Json]]

implicit val lcs = new Patience[Json]

val json1 = parse(of1)
val json2 = parse(of2)

val patch =
  for {
    json1 <- json1
    json2 <- json2
  } yield diff(json1, json2)

print(patch)
  

Это дает:

 Right(JsonPatch(List(Replace(Chain(Left(keyA), Left(0)),201,None), Replace(Chain(Left(keyA), Left(1)),12,None))))
  

посмотрите, как это работает https://index.scala-lang.org/gnieh/diffson/diffson-circe/4.0.3?target=_2.13

Для Circe, укажите зависимость:

 "org.gnieh" %% f"diffson-circe" % "4.0.3"
  

Комментарии:

1. Я уже использую jackson в других модулях. Хотелось бы придерживаться jackson для любых требований к синтаксическому анализу.