Scala JSON4S обработки пустых полей

Это два образца данных JSON.

pattern1

{
  "data_type": "stats",
  "data": [
    {
      "id" : "123abc",
      "promoted_tweet_timeline_card_engagements": [ 0 ],
      "promoted_account_follow_rate": [ 0 ],
      "conversion_sign_ups": [ 0 ] // <- sometime not passed this field
    }
  ]
}

и, иногда, не пройденное поле

pattern2

{
  "data_type": "stats",
  "data": [
    {
      "id" : "123abc",
      "promoted_tweet_timeline_card_engagements": [ 0 ],
      "promoted_account_follow_rate": [ 0 ]
    }
  ]
}

Я хочу преобразовать в этот класс дела.

case class Campaign(
  id: String,
  promoted_tweet_timeline_card_engagements: List[Any],
  promoted_account_follow_rate: List[Any],
  conversion_sign_ups: Option[List[Any]],
)

это основной код

for {
      JObject(data) <- json \\ "data"
      JField("id", JString(id)) <- data
      JField("promoted_tweet_timeline_card_engagements", JArray(promoted_tweet_timeline_card_engagements)) <- data
      JField("promoted_account_follow_rate", JArray(promoted_account_follow_rate)) <- data
      JField("conversion_sign_ups", JArray(conversion_sign_ups)) <- data // It can not be handled correctly when field does not exists
    } yield Campaign(
        id = id,
        promoted_tweet_timeline_card_engagements = promoted_tweet_timeline_card_engagements,
        promoted_account_follow_rate = promoted_account_follow_rate,
        conversion_sign_ups = Option(conversion_sign_ups)
    )

conversion_sign_ups поля не могут быть обработаны правильно, когда данные pattern2.

Я хочу справиться с этим в одном случае класса. Как я должен это делать??

2 ответа

Проблема, кажется, заключается в следующем:

JField("conversion_sign_ups", JArray(conversion_sign_ups)) <- data

Когда объект json в данных не содержит поля translation_sign_ups. окончательное сопоставление с образцом не удастся, что приведет к сбою всего совпадения по шаблону Вот обходной путь для вас.

val result = for {
    JObject(data) <- json \\ "data"
    JField("id", JString(id)) <- data
    JField("promoted_tweet_timeline_card_engagements", 
       JArray(promoted_tweet_timeline_card_engagements)) <- data
    JField("promoted_account_follow_rate",
       JArray(promoted_account_follow_rate)) <- data
    // try to get the conversion_sign_ups field value
    signUpOpt = data.find(_._1 == "conversion_sign_ups").map(_._2)
} yield {
    Campaign(
        id = id,
        promoted_tweet_timeline_card_engagements = promoted_tweet_timeline_card_engagements,
        promoted_account_follow_rate = promoted_account_follow_rate,
        conversion_sign_ups = signUpOpt.flatMap {
            case JArray(conversion_sign_ups) => Some(conversion_sign_ups)
            case _ => None
        }
    )
}

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

val out = for {
  JObject(data) <- json \\ "data"
  JField("id", JString(id)) <- data
  JField("promoted_tweet_timeline_card_engagements", JArray(promoted_tweet_timeline_card_engagements)) <- data
  JField("promoted_account_follow_rate", JArray(promoted_account_follow_rate)) <- data
} yield {

    val conversion_sign_ups = (json \\ "conversion_sign_ups") match {
      case JArray(sign_ups) => Some(sign_ups)
      case _ => None
    }

    Campaign(
      id,
      promoted_tweet_timeline_card_engagements,
      promoted_account_follow_rate,
      conversion_sign_ups
    )
  }
Другие вопросы по тегам