huangbiubiu
huangbiubiu

Reputation: 1271

Process json with different data type in Circe

In my case, there might be different data type of same json field. Example:

"need_exp":1500

or

"need_exp":"-"

How to process this case? I know it can be processed by parse or use custom encoders, but this is a very complex json text, is there any way to solve that without rewriting the whole decoder (for example, just "tell" the decoder to convert all Int to String in need_exp field)?

Upvotes: 1

Views: 524

Answers (2)

huangbiubiu
huangbiubiu

Reputation: 1271

My solution is to use a custom decoder. Rewrite a little part of the JSON can be fine.

For example, there is a simple JSON:

{  
   /*many fields*/
   "hotList":[/* ... many lists inside*/],
   "list":[ {/*... many fields*/
         "level_info":{  
            "current_exp":11463,
            "current_level":5,
            "current_min":10800,
            "next_exp":28800 //there is the problem
         },
         "sex":"\u4fdd\u5bc6"},/*...many lists*/]
}

In this case, I don't need to rewrite the whole JSON encoder, just write a custom encoder of level_info:

implicit val decodeUserLevel: Decoder[UserLevel] = (c: HCursor) => for
{
    current_exp <- c.downField("current_exp").as[Int]
    current_level <- c.downField("current_level").as[Int]
    current_min <- c.downField("current_min").as[Int]
    next_exp <- c.downField("next_exp").withFocus(_.mapString
    {
        case """-""" => "-1"
        case default => default
    }).as[Int]
} yield
{
    UserLevel(current_exp, current_level, current_min, next_exp)
}

and it worked.

Upvotes: 1

n1r3
n1r3

Reputation: 8913

It is called a disjunction which can be encoded with the Scala standard Either class. Simply map the json that to the following class:

case class Foo(need_exp: Either[String, Int])

Upvotes: 2

Related Questions