All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.outworkers.util.lift.Serializers.scala Maven / Gradle / Ivy

There is a newer version: 0.50.0
Show newest version
/*
 * Copyright 2013 - 2017 Outworkers Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.outworkers.util.lift

import java.util.UUID

import net.liftweb.json.JsonAST.{JString, JValue}
import net.liftweb.json._
import org.joda.time.{DateTime, DateTimeZone}

import scala.reflect.ClassTag
import scala.util.{Failure, Success, Try}
import scala.util.control.NonFatal

sealed class UUIDSerializer extends Serializer[UUID] {
  private[this] val uuidClz = classOf[UUID]

  def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), UUID] = {
    case (TypeInfo(uuidClz, _), json) => json match {
      case JString(value) => try {
        UUID.fromString(value)
      }  catch {
        case NonFatal(err) => {
          val exception = new MappingException(s"Couldn't extract an UUID from $value")
          exception.initCause(err)
          throw exception
        }
      }
      case x => throw new MappingException(s"Can't convert $x to UUID")
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case x: UUID => JString(x.toString)
  }
}

class EnumSerializer[E <: Enumeration: ClassTag](enum: E)
  extends Serializer[E#Value] {
  import JsonDSL._

  val enumClz = classOf[E#Value]

  def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = {
    case (TypeInfo(`enumClz`, _), json) => json match {
      case JInt(value) if value <= enum.maxId => enum(value.toInt)
      case value => throw new MappingException(s"Can't convert $value to $enumClz")
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case i: E#Value => i.id
  }
}

sealed class DateTimeSerializer extends Serializer[DateTime] {

  val dateTimeClz = classOf[DateTime]

  def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), DateTime] = {
    case (TypeInfo(`dateTimeClz`, _), json) => json match {
      case JString(value) =>
        Try {
          new DateTime(value.toLong, DateTimeZone.UTC)
        } match {
          case Success(dt) => dt
          case Failure(err) =>
            val exception = new MappingException(s"Couldn't extract a DateTime from $value")
            exception.initCause(err)
            throw exception
        }
      case JInt(value) => {
        Try(new DateTime(value.toLong, DateTimeZone.UTC)) match {
          case Success(dt) => dt
          case Failure(err) =>
            val exception = new MappingException(s"Couldn't extract a DateTime from $value")
            exception.initCause(err)
            throw exception
        }
      }
      case x => throw new MappingException(s"Can't convert $x to DateTime")
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case x: DateTime => JInt(x.getMillis)
  }
}

class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E)
  extends Serializer[E#Value] {
  import JsonDSL._

  val EnumerationClass = classOf[E#Value]

  def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = {
    case (TypeInfo(EnumerationClass, _), json) => json match {
      case JString(value) if enum.values.exists(_.toString == value) => enum.withName(value)
      case value => throw new MappingException(s"Can't convert $value to $EnumerationClass")
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case i: E#Value => i.toString
  }
}


object EnumNameSerializer {
  def apply[E <: Enumeration : ClassTag](enum: E): EnumNameSerializer[E] = {
    new EnumNameSerializer(enum)
  }
}

trait CustomSerializers {
  implicit val formats = Serialization.formats(NoTypeHints) + new UUIDSerializer + new DateTimeSerializer
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy