Mapping between Scala Enumeration and Integer / String in DB by Slick

You can convert only primitive types as default. If you want to map user defined types including Enumeration, you need to defined implicit mapping function using MappedColumnType. Please see "USER-DEFINED FEATURES" in the official doccument for more details.

Note)Here is my current environment. * Scala 2.11.6 * Slick 3.1.0

Enumeration define

// enum that is converted to String
object Color extends Enumeration {
  type Color = Value
  val Blue = Value("Blue")
  val Red = Value("Red")
  val Green = Value("Green")
}

// enum that is converted to int
object Bar extends Enumeration {
  type Bar = Value
  val b1 = Value
  val b2 = Value
  val b3 = Value
}

Table definition in Slick

You can use Enumeration in column definition. Please not that I defined implicit mapping functions.

class SampleTable(tag: Tag) extends Table[Sample](tag, "Sample") {
  def name  = column[String]("NAME")
  def id    = column[Int]("ID")
  def color = column[Color]("COLOR")
  def bar   = column[Bar]("BAR")
  def * = (name, id, color, bar) <> (Sample.tupled, Sample.unapply)
}
implicit val colorMapper = MappedColumnType.base[Color, String](
  e => e.toString,
  s => Color.withName(s)
)
implicit val barMapper = MappedColumnType.base[Bar, Int](
  e => e.id,
  i => Bar.apply(i)
)

Serialize / deserialize Object as #msgpack Array

MessagePack for Java supports serialization and deserialization of Java objects with jackson-databind. But ObjectMapper in jackson-databind serialize Java object to map format data.

If you want to serialize Java Object to array format data, or deserialize array format data to Java Object. You must specify an annotation @JsonFormat(shape=JsonFormat.Shape.ARRAY) on the definition of the object you want to deal with.

For example, if you want to serialize/deserialize the following class, you add an annotation @JsonFormat on the class.

@JsonFormat(shape=JsonFormat.Shape.ARRAY)
public class Point {
    private int x;
    private int y;

    public Point() {}
    public Point(int x, int y) {this.x=x;this.y=y;}

    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
}

You can serialize it as follows.

Point p = new Point(1,2);
ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
try {
    byte[] bytes = mapper.writeValueAsBytes(p);
    assertThat(bytes[0], is((byte)0x92));
    assertThat(bytes[1], is((byte)1));
    assertThat(bytes[2], is((byte)2));
    Point p1 = mapper.readValue(bytes, new TypeReference<Point>(){});
    assertThat(p1.getX(), is(1));
    assertThat(p1.getY(), is(2));
} catch (IOException e) {
    e.printStackTrace();
}

You can also deserialize.

byte[] a = new byte[]{(byte)0x92,1,2};
ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
try {
    Point p = mapper.readValue(a, new TypeReference<Point>(){});
    assertThat(p.getX(), is(1));
    assertThat(p.getY(), is(2));
} catch (IOException e) {
    e.printStackTrace();
}