2015-08-10 2 views
2

Я использую Gson для сериализации и десериализации объектов и сохранения результатов в Redis. т.е. объект сериализуется в строку json, а затем помещается в Redis, когда объект возвращается, это строка, тогда я использую Gson.fromjson (str, className) для десериализации в объект.Сериализация/десериализация объектов с помощью Gson в Scala

Я начинаю с Scala, поэтому предполагаю, что мое использование неверно.

У меня есть следующий класс:

case class Status(id: String, state: State) 

, где государство является следующее:

sealed trait State {} 

case object COMPLETED_SUCCESSFULLY extends State {} 

case object FINISHED_POLLING extends State {} 

case object CURRENTLY_DOWNLOADING extends State {} 

case object FINISHED_DOWNLOADING extends State {} 

case object CURRENTLY_UPLOADING extends State {} 

case object FINISHED_UPLOADING extends State {} 

Я хочу сериализации Status в строку JSON затем десериализации его обратно в объект.

Но, когда я сериализации Status с помощью Gson, я получаю:

"{\"id\":\"foo\",\"state\":{}}" 

Почему?

Ex:

val Status = new Status("foo", COMPLETED_SUCCESSFULLY) 

Я ожидаю сериализованные выход быть

"{\"id\":\"foo\",\"state\":\"COMPLETED_SUCCESSFULLY\"}" 
+1

Какой результат вы ожидаете? – ka4eli

+0

@ ka4eli обновленный вопрос. Я просто хочу иметь возможность сериализации и десериализации с помощью gson. – iCodeLikeImDrunk

ответ

3

По умолчанию, тематические объекты сериализуются Gson с пустыми объектами JSon: {}. Вы должны написать собственный сериалайзер, чтобы получить ожидаемое поведение:

object StateSerializer extends JsonSerializer[State] { 
    override def serialize(t1: State, t2: Type, jsonSerializationContext: JsonSerializationContext): JsonElement = { 
    val res = new JsonObject() 
    res.add("name", new JsonPrimitive(t1.toString)) 
    res 
    } 
} 


val gson = new GsonBuilder().registerTypeHierarchyAdapter(classOf[State], StateSerializer) 
.registerTypeHierarchyAdapter(classOf[State], StateDeserializer).setPrettyPrinting().create() 

println(gson.toJson(COMPLETED_SUCCESSFULLY)) 

Напечатает:

{ 
    "name": "COMPLETED_SUCCESSFULLY" 
} 

Кроме того, если вы хотите, чтобы преобразовать JSON в случае объекта вы должны реализовать JsonDeserializer:

object StateDeserializer extends JsonDeserializer[State] { 
    override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): State = { 
    val res = json match { 
     case o: JsonObject if o.has("name") && o.entrySet().size() == 1 => 
     val name = o.get("name").getAsString 
     name match { 
      case "FINISHED_POLLING" => FINISHED_POLLING 
      case "FINISHED_DOWNLOADING" => FINISHED_DOWNLOADING 
      case "FINISHED_UPLOADING" => FINISHED_UPLOADING 
      case "CURRENTLY_DOWNLOADING" => CURRENTLY_DOWNLOADING 
      case "CURRENTLY_UPLOADING" => CURRENTLY_UPLOADING 
      case "COMPLETED_SUCCESSFULLY" => COMPLETED_SUCCESSFULLY 
      case _ => null 
     } 
     case _ => null 
    } 

    Option(res).getOrElse(throw new JsonParseException(s"$json can't be parsed to State")) 
    } 
} 

println(gson.fromJson("{\"name\": \"COMPLETED_SUCCESSFULLY\"}", classOf[State])) 

Будет ли печатать:

COMPLETED_SUCCESSFULLY 
+0

это означало бы, что я должен написать сериализатор для каждого перечисления, которое у меня есть? – iCodeLikeImDrunk

+0

также, для deserialize, я не могу просто сделать gson.fromJson (String, classOf [Status])? – iCodeLikeImDrunk

+0

обновил ответ. Теперь у вас есть один сериализатор для всех состояний. Да, вы не можете. Поскольку Gson не знает, что это '{ " name ":" COMPLETED_SUCCESSFULLY " }' соответствует 'COMPLETED_SUCCESSFULLY'. – ka4eli

Смежные вопросы