Circe Не удалось преобразовать необработанный json в класс case Ошибка: не удалось найти неявное значение Lazy типа io.circe.generic.decoding.DerivedDecoder. - PullRequest
0 голосов
/ 11 января 2019

Я определил пару классов case для представления JSON, но я не уверен, правильно ли я это сделал, так как существует множество вложенных классов case. Объекты типа spec, meta и т. Д. Имеют тип JSONObject, а также сам объект Custom.

Вот все классы, которые я определил:

  case class CustomObject(apiVersion: String,kind: String, metadata: Metadata,spec: Spec,labels: Object,version: String)

  case class Metadata(creationTimestamp: String, generation: Int, uid: String,resourceVersion: String,name: String,namespace: String,selfLink: String)

  case class Spec(mode: String,image: String,imagePullPolicy: String, mainApplicationFile: String,mainClass: String,deps: Deps,driver: Driver,executor: Executor,subresources: Subresources)

  case class Driver(cores: Double,coreLimit: String,memory: String,serviceAccount: String,labels: Labels)

  case class Executor(cores: Double,instances: Double,memory: String,labels: Labels)

  case class Labels(version: String)

  case class Subresources(status: Status)

  case class Status()

  case class Deps()

И это структура JSON для пользовательского объекта K8s, который мне нужно преобразовать:

{
    "apiVersion": "sparkoperator.k8s.io/v1alpha1",
    "kind": "SparkApplication",
    "metadata": {
        "creationTimestamp": "2019-01-11T15:58:45Z",
        "generation": 1,
        "name": "spark-example",
        "namespace": "default",
        "resourceVersion": "268972",
        "selfLink": "/apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-example",
        "uid": "uid"
    },
    "spec": {
        "deps": {},
        "driver": {
            "coreLimit": "1000m",
            "cores": 0.1,
            "labels": {
                "version": "2.4.0"
            },
            "memory": "1024m",
            "serviceAccount": "default"
        },
        "executor": {
            "cores": 1,
            "instances": 1,
            "labels": {
                "version": "2.4.0"
            },
            "memory": "1024m"
        },
        "image": "gcr.io/ynli-k8s/spark:v2.4.0,
        "imagePullPolicy": "Always",
        "mainApplicationFile": "http://localhost:8089/spark_k8s_airflow.jar",
        "mainClass": "org.apache.spark.examples.SparkExample",
        "mode": "cluster",
        "subresources": {
            "status": {}
        },
        "type": "Scala"
    }
}

UPDATE: Я хочу преобразовать JSON в case-классы с помощью Circe, однако с такими классами я сталкиваюсь с этой ошибкой:

Error: could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[dataModel.CustomObject]
    implicit val customObjectDecoder: Decoder[CustomObject] = deriveDecoder[CustomObject]

Я определил неявные декодеры для всех классов дел:

 implicit val customObjectLabelsDecoder: Decoder[Labels] = deriveDecoder[Labels]
    implicit val customObjectSubresourcesDecoder: Decoder[Subresources] = deriveDecoder[Subresources]
    implicit val customObjectDepsDecoder: Decoder[Deps] = deriveDecoder[Deps]
    implicit val customObjectStatusDecoder: Decoder[Status] = deriveDecoder[Status]
    implicit val customObjectExecutorDecoder: Decoder[Executor] = deriveDecoder[Executor]
    implicit val customObjectDriverDecoder: Decoder[Driver] = deriveDecoder[Driver]
    implicit val customObjectSpecDecoder: Decoder[Spec] = deriveDecoder[Spec]
    implicit val customObjectMetadataDecoder: Decoder[Metadata] = deriveDecoder[Metadata]
    implicit val customObjectDecoder: Decoder[CustomObject] = deriveDecoder[CustomObject]

Ответы [ 2 ]

0 голосов
/ 12 января 2019

Причина, по которой вы не можете получить декодирование для CustomObject, заключается в члене labels: Object.

В Circe все декодирование осуществляется статическими типами, и Circe не предоставляет кодеры или декодеры для таких типов, как Object или Any, которые не имеют полезной статической информации.

Если вы измените этот класс дел на что-то вроде следующего:

case class CustomObject(apiVersion: String, kind: String, metadata: Metadata, spec: Spec)

… и оставьте оставшуюся часть кода без изменений при импорте:

import io.circe.Decoder, io.circe.generic.semiauto.deriveDecoder

И определите ваш документ JSON как doc (после добавления кавычки в строку "image": "gcr.io/ynli-k8s/spark:v2.4.0,, чтобы сделать его действительным JSON), следующее должно работать нормально:

scala> io.circe.jawn.decode[CustomObject](doc)
res0: Either[io.circe.Error,CustomObject] = Right(CustomObject(sparkoperator.k8s.io/v1alpha1,SparkApplication,Metadata(2019-01-11T15:58:45Z,1,uid,268972,spark-example,default,/apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-example),Spec(cluster,gcr.io/ynli-k8s/spark:v2.4.0,Always,http://localhost:8089/spark_k8s_airflow.jar,org.apache.spark.examples.SparkExample,Deps(),Driver(0.1,1000m,1024m,default,Labels(2.4.0)),Executor(1.0,1.0,1024m,Labels(2.4.0)),Subresources(Status()))))

Несмотря на то, что говорит один из других ответов, Circe может определенно получить кодировщики и декодеры для классов дел без членов - здесь определенно не проблема.

В качестве дополнительного примечания, я хотел бы иметь возможность получать сообщения об ошибках лучше, чем это:

Error: could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[dataModel.CustomObject

Но, учитывая, что circe-generic должен использовать Lazy Shapeless прямо сейчас, это лучшее, что мы можем получить. Вы можете попробовать circe-Derivation в качестве альтернативы в основном для полуавтоматического вывода Circe-generic, который имеет лучшие сообщения об ошибках (и некоторые другие преимущества), или вы можете использовать плагин компилятора, такой как splain , который специально разработан, чтобы выдавать лучшие сообщения об ошибках даже при наличии таких вещей, как shapeless.Lazy.

В качестве заключительного замечания вы можете немного очистить ваши полуавтоматические определения, позволив выводить параметр типа для deriveDecoder:

implicit val customObjectLabelsDecoder: Decoder[Labels] = deriveDecoder

Это дело вкуса, но я считаю, что читать его немного менее шумно.

0 голосов
/ 11 января 2019

выглядит правильно для меня. Вы сталкиваетесь с какой-либо проблемой?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...