Декодировать List[String] в List[JSONObject(key,value)] в circe scala

Учитывая входящий json, как показано ниже, как я могу декодировать его для данного класса case на основе условия.

Входящий JSON

{
    "config": {
        "files": ["welcome"],
        "channel": "media"
    }
}

Классы случаев

case class File(`type`: String, value: String)

case class Config(files: List[File],
                  channel: String = "BC")

object Config{
  implicit val FileDecoder: Decoder[File] = deriveDecoder[File]
  implicit val ConfigDecoder: Decoder[Config] = deriveDecoder[Config]
}

case class Inventory(config: Config)

object Inventory {
  implicit val InventoryDecoder: Decoder[Inventory] = deriveDecoder[Inventory]
}

У меня нет контроля над значениями входящих файлов в json, это может быть List [String] или List [File], поэтому мне нужно обрабатывать оба случая в моей логике декодирования.

Итак, как мы видим выше, моя цель - проверить, являются ли значения файлов доходов списком [String], а затем преобразовать эти значения ниже, где тип жестко запрограммирован на «аудио».

"files": [{
            "type": "audio",
            "value": "welcome.mp3"
        }],

Общий json должен выглядеть так, как показано ниже, прежде чем он будет сопоставлен с классами case для автоматического декодирования.

{
    "config": {
        "files": [{
            "type": "audio",
            "value": "welcome.mp3"
        }],
        "channel": "media"
    }
}

что я понял, что этого можно добиться либо путем преобразования json перед декодированием, либо также можно добиться во время декодирования файлов.

Я пытался написать логику декодирования на уровне файла, но у меня не получилось. Я не понимаю, как это сделать.

Пробный код

  implicit val FileDecoder: Decoder[File] = deriveDecoder[File].prepare { (aCursor: ACursor) =>
  {

    if(!aCursor.values.contains("type")){
      aCursor.values.map( v =>
        Json.arr(
          Json.fromFields(
            Seq(
              ("type", Json.fromString("audio")),
              ("value", v.head)
            )
          )
        )
      )
    }
  }
  }
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
0
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мы можем использовать пользовательский Decoder для File, чтобы указать значение по умолчанию для type

final case class File(`type`: String, value: String)
object File {
  implicit final val FileDecoder: Decoder[File] =
    Decoder.instance { cursor =>
      (
        cursor.getOrElse[String](k = "type")(fallback = "audio"),
        cursor.get[String](k = "value")
      ).mapN(File.apply)
    }.or(
      Decoder[String].map(value => File(`type` = "audio", value))
    )
}

Что можно использовать так:

val data =
"""[
  {
    "type": "audio",
    "value": "welcome.mp3"
  },
  {
    "value": "foo.mp3"
  },
  "bar.mp3"
]"""

parser.decode[List[File]](data)
// res: Either[io.circe.Error, List[File]] =
//  Right(List(
//    File("audio", "welcome.mp3"),
//    File("audio", "foo.mp3"),
//    File("audio", "bar.mp3")
//  ))

Вы можете увидеть код, выполняющий здесь.

Прежде всего, спасибо за изучение этого Луиса. Я понял пример, который вы пробовали, но в моем сценарии у нас есть входящие данные файла, такие как List[String], например. val data = """["welcome.mp3"]""" который должен быть преобразован в """ [{ "type": "audio", "value": "welcome.mp3" }] """

Arpit Bhardwaj 09.04.2022 18:03

@ArpitBhardwaj эй, извините за отсутствие этой детали, я только что отредактировал ответ, указав альтернативу, которая поддерживает любой из трех вариантов :)

Luis Miguel Mejía Suárez 09.04.2022 19:24

Другие вопросы по теме