alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (ExtractionExamplesSpec.scala)

This example Lift Framework source code file (ExtractionExamplesSpec.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

address, bulevard, helsinki, helsinki, int, list, list, map, map, multipleconstructors, none, some, string, string, util

The Lift Framework ExtractionExamplesSpec.scala source code

/*
 * Copyright 2009-2011 WorldWide Conferencing, LLC
 *
 * 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 net.liftweb
package json

import java.util.Date
import org.specs.Specification

object ExtractionExamples extends Specification("Extraction Examples Specification") {
  implicit val formats = DefaultFormats

  "Extraction example" in {
    val json = parse(testJson)
    json.extract[Person] mustEqual Person("joe", Address("Bulevard", "Helsinki"), List(Child("Mary", 5, Some(date("2004-09-04T18:06:22Z"))), Child("Mazy", 3, None)))
  }

  "Extraction with path expression example" in {
    val json = parse(testJson)
    (json \ "address").extract[Address] mustEqual Address("Bulevard", "Helsinki")
  }

  "Partial extraction example" in {
    val json = parse(testJson)
    json.extract[SimplePerson] mustEqual SimplePerson("joe", Address("Bulevard", "Helsinki"))
  }

  "Extract with a default value" in {
    val json = parse(testJson)
    (json \ "address2").extractOrElse(Address("Tie", "Helsinki")) mustEqual Address("Tie", "Helsinki")
  }

  "Map with primitive values extraction example" in {
    val json = parse(testJson)
    json.extract[PersonWithMap] mustEqual 
      PersonWithMap("joe", Map("street" -> "Bulevard", "city" -> "Helsinki"))
  }

  "Map with object values extraction example" in {
    val json = parse(twoAddresses)
    json.extract[PersonWithAddresses] mustEqual 
      PersonWithAddresses("joe", Map("address1" -> Address("Bulevard", "Helsinki"),
                                     "address2" -> Address("Soho", "London")))
  }

  "Simple value extraction example" in {
    val json = parse(testJson)
    json.extract[Name] mustEqual Name("joe")
    (json \ "children")(0).extract[Name] mustEqual Name("Mary")
    (json \ "children")(1).extract[Name] mustEqual Name("Mazy")
  }

  "Primitive value extraction example" in {
    val json = parse(testJson)
    (json \ "name").extract[String] mustEqual "joe"
    (json \ "name").extractOpt[String] mustEqual Some("joe")
    (json \ "name").extractOpt[Int] mustEqual None
    ((json \ "children")(0) \ "birthdate").extract[Date] mustEqual date("2004-09-04T18:06:22Z")

    JInt(1).extract[Int] mustEqual 1
    JInt(1).extract[String] mustEqual "1"
    JField("foo", JInt(1)).extract[Int] mustEqual 1
  }

  "Primitive extraction example" in {
    val json = parse(primitives)
    json.extract[Primitives] mustEqual Primitives(124, 123L, 126.5, 127.5.floatValue, "128", 'symb, 125, 129.byteValue, true)
  }

  "Null extraction example" in {
    val json = parse("""{ "name": null, "age": 5, "birthdate": null }""")
    json.extract[Child] mustEqual Child(null, 5, None)
  }

  "Date extraction example" in {
    val json = parse("""{"name":"e1","timestamp":"2009-09-04T18:06:22Z"}""")
    json.extract[Event] mustEqual Event("e1", date("2009-09-04T18:06:22Z"))
  }

  "Option extraction example" in {
    val json = parse("""{ "name": null, "age": 5, "mother":{"name":"Marilyn"}}""")
    json.extract[OChild] mustEqual OChild(None, 5, Some(Parent("Marilyn")), None)
  }

  "Missing JSON array can be extracted as an empty List" in {
    parse(missingChildren).extract[Person] mustEqual Person("joe", Address("Bulevard", "Helsinki"), Nil)
  }

  "Multidimensional array extraction example" in {
    parse(multiDimensionalArrays).extract[MultiDim] mustEqual MultiDim(
      List(List(List(1, 2), List(3)), List(List(4), List(5, 6))), 
      List(List(Name("joe"), Name("mary")), List(Name("mazy"))))
  }
  
  "Flatten example with simple case class" in {
    val f = Extraction.flatten(Extraction.decompose(SimplePerson("joe", Address("Bulevard", "Helsinki"))))
    val e = Map(".name" -> "\"joe\"", ".address.street" -> "\"Bulevard\"", ".address.city"   -> "\"Helsinki\"")
    
    f mustEqual e
  }
  
  "Unflatten example with top level string and int" in {
    val m = Map(".name" -> "\"joe\"", ".age" -> "32")
    
    Extraction.unflatten(m) mustEqual JObject(List(JField("name",JString("joe")), JField("age",JInt(32))))
  }
  
  "Unflatten example with top level string and double" in {
    val m = Map(".name" -> "\"joe\"", ".age" -> "32.2")
  
    Extraction.unflatten(m) mustEqual JObject(List(JField("name",JString("joe")), JField("age",JDouble(32.2))))
  }
  
  "Unflatten example with two-level string properties" in {
    val m = Map(".name" -> "\"joe\"", ".address.street" -> "\"Bulevard\"", ".address.city"   -> "\"Helsinki\"")
    
    Extraction.unflatten(m) mustEqual JObject(List(JField("name", JString("joe")), JField("address", JObject(List(JField("street", JString("Bulevard")), JField("city", JString("Helsinki")))))))
  }
  
  "Unflatten example with top level array" in {
    val m = Map(".foo[2]" -> "2", ".foo[0]" -> "0", ".foo[1]" -> "1")
    
    Extraction.unflatten(m) mustEqual JObject(List(JField("foo", JArray(List(JInt(0), JInt(1), JInt(2))))))
  }
  
  "Flatten and unflatten are symmetric" in {
    val parsed = parse(testJson)
    
    Extraction.unflatten(Extraction.flatten(parsed)) mustEqual parsed
  }
  
  "Flatten preserves empty sets" in {
    val s = SetWrapper(Set())
    
    Extraction.flatten(Extraction.decompose(s)).get(".set") mustEqual Some("[]")
  }
  
  "Flatten and unflatten are symmetric with empty sets" in {
    val s = SetWrapper(Set())
    
    Extraction.unflatten(Extraction.flatten(Extraction.decompose(s))).extract[SetWrapper] mustEqual s
  }

  "List extraction example" in {
    val json = parse(testJson) \ "children"
    json.extract[List[Name]] mustEqual List(Name("Mary"), Name("Mazy"))
  }

  "Map extraction example" in {
    val json = parse(testJson) \ "address"
    json.extract[Map[String, String]] mustEqual Map("street" -> "Bulevard", "city" -> "Helsinki")
  }

  "Extraction and decomposition are symmetric" in {
    val person = parse(testJson).extract[Person]
    Extraction.decompose(person).extract[Person] mustEqual person
  }

  "Extraction failure message example" in {
    val json = parse("""{"city":"San Francisco"}""")
    json.extract[Address] must throwA(MappingException("No usable value for street\nDid not find value which can be converted into java.lang.String", null))
  }

  "Best matching constructor selection example" in {
    parse("""{"name":"john","age":32,"size":"M"}""").extract[MultipleConstructors] mustEqual
      MultipleConstructors("john", 32, Some("M"))

    parse("""{"name":"john","age":32}""").extract[MultipleConstructors] mustEqual
      MultipleConstructors("john", 32, Some("S"))

    parse("""{"name":"john","foo":"xxx"}""").extract[MultipleConstructors] mustEqual
      MultipleConstructors("john", 30, None)

    parse("""{"name":"john","age":32,"size":null}""").extract[MultipleConstructors] mustEqual
      MultipleConstructors("john", 32, None)

    parse("""{"birthYear":1990,"name":"john","foo":2}""").extract[MultipleConstructors] mustEqual
      MultipleConstructors("john", 20, None)

    parse("""{"foo":2,"age":12,"size":"XS"}""").extract[MultipleConstructors] mustEqual
      MultipleConstructors("unknown", 12, Some("XS"))
  }

  "Partial JSON extraction" in {
    parse(stringField).extract[ClassWithJSON] mustEqual ClassWithJSON("one", JString("msg"))
    parse(objField).extract[ClassWithJSON] mustEqual ClassWithJSON("one", JObject(List(JField("yes", JString("woo")))))
  }

  "Double can be coerced to Int or Long" in {
    JDouble(2.1).extract[Int] mustEqual 2
    JDouble(2.1).extract[Long] mustEqual 2L
  }

  "Map with nested non-polymorphic list extraction example" in {
    parse("""{"a":["b"]}""").extract[Map[String, List[String]]] mustEqual Map("a" -> List("b"))
  }

  "List with nested non-polymorphic list extraction example" in {
    parse("""[["a"]]""").extract[List[List[String]]] mustEqual List(List("a"))
  }

  "Complex nested non-polymorphic collections extraction example" in {
    parse("""{"a":[{"b":"c"}]}""").extract[Map[String, List[Map[String, String]]]] mustEqual Map("a" -> List(Map("b" -> "c")))
  }

  val testJson = 
"""
{ "name": "joe",
  "address": {
    "street": "Bulevard",
    "city": "Helsinki"
  },
  "children": [
    {
      "name": "Mary",
      "age": 5
      "birthdate": "2004-09-04T18:06:22Z"
    },
    {
      "name": "Mazy",
      "age": 3
    }
  ]
}
"""

  val missingChildren =
"""
{
  "name": "joe",
  "address": {
    "street": "Bulevard",
    "city": "Helsinki"
  }
}
"""

  val twoAddresses =
"""
{
  "name": "joe",
  "addresses": {
    "address1": {
      "street": "Bulevard",
      "city": "Helsinki"
    },
    "address2": {
      "street": "Soho",
      "city": "London"
    }
  }
}
"""

  val primitives = 
"""
{
  "l": 123,
  "i": 124,
  "sh": 125,
  "d": 126.5,
  "f": 127.5,
  "s": "128",
  "b": 129,
  "bool": true,
  "sym":"symb"
}
"""

  val multiDimensionalArrays =
"""
{
  "ints": [[[1, 2], [3]], [[4], [5, 6]]],
  "names": [[{"name": "joe"}, {"name": "mary"}], [[{"name": "mazy"}]]]
}
"""

  val stringField =
"""
{
  "name": "one",
  "message": "msg"
}
"""

  val objField =
"""
{
  "name": "one",
  "message": {
    "yes": "woo"
  }
}
"""

  def date(s: String) = DefaultFormats.dateFormat.parse(s).get
}

case class SetWrapper(set: Set[String])

case class Person(name: String, address: Address, children: List[Child])
case class Address(street: String, city: String)
case class Child(name: String, age: Int, birthdate: Option[java.util.Date])

case class SimplePerson(name: String, address: Address)

case class PersonWithMap(name: String, address: Map[String, String])
case class PersonWithAddresses(name: String, addresses: Map[String, Address])

case class Name(name: String)

case class Primitives(i: Int, l: Long, d: Double, f: Float, s: String, sym: Symbol, sh: Short, b: Byte, bool: Boolean)

case class OChild(name: Option[String], age: Int, mother: Option[Parent], father: Option[Parent])
case class Parent(name: String)

case class Event(name: String, timestamp: Date)

case class MultiDim(ints: List[List[List[Int]]], names: List[List[Name]])

case class MultipleConstructors(name: String, age: Int, size: Option[String]) {
  def this(name: String) = this(name, 30, None)
  def this(age: Int, name: String) = this(name, age, Some("S"))
  def this(name: String, birthYear: Int) = this(name, 2010 - birthYear, None)
  def this(size: Option[String], age: Int) = this("unknown", age, size)
}

case class ClassWithJSON(name: String, message: JValue)

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework ExtractionExamplesSpec.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.