haldr

HAL builder for spray-json

License

License

MIT
GroupId

GroupId

com.github.ancane
ArtifactId

ArtifactId

haldr_2.13
Last Version

Last Version

0.5
Release Date

Release Date

Type

Type

jar
Description

Description

haldr
HAL builder for spray-json
Project URL

Project URL

https://github.com/ancane/haldr
Project Organization

Project Organization

com.github.ancane
Source Code Management

Source Code Management

https://github.com/ancane/haldr

Download haldr_2.13

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.ancane/haldr_2.13/ -->
<dependency>
    <groupId>com.github.ancane</groupId>
    <artifactId>haldr_2.13</artifactId>
    <version>0.5</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.ancane/haldr_2.13/
implementation 'com.github.ancane:haldr_2.13:0.5'
// https://jarcasting.com/artifacts/com.github.ancane/haldr_2.13/
implementation ("com.github.ancane:haldr_2.13:0.5")
'com.github.ancane:haldr_2.13:jar:0.5'
<dependency org="com.github.ancane" name="haldr_2.13" rev="0.5">
  <artifact name="haldr_2.13" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.ancane', module='haldr_2.13', version='0.5')
)
libraryDependencies += "com.github.ancane" % "haldr_2.13" % "0.5"
[com.github.ancane/haldr_2.13 "0.5"]

Dependencies

compile (4)

Group / Artifact Type Version
org.scala-lang : scala-library jar 2.13.4
io.spray : spray-json_2.13 jar 1.3.6
com.typesafe.akka : akka-http_2.13 jar 10.1.13
com.typesafe.akka : akka-http-spray-json_2.13 jar 10.1.13

provided (1)

Group / Artifact Type Version
com.typesafe.akka : akka-actor_2.13 jar 2.5.32

test (4)

Group / Artifact Type Version
com.typesafe.akka : akka-http-testkit_2.13 jar 10.1.13
com.typesafe.akka : akka-testkit_2.13 jar 2.5.32
org.specs2 : specs2-core_2.13 jar 4.10.6
com.typesafe.akka : akka-stream_2.13 jar 2.5.32

Project Modules

There are no modules declared in this project.

HALdr

HAL resource representations builder for spray-json

Usage

Cross-built for Scala 2.11, 2.12, 2.13

libraryDependencies += "com.github.ancane" %% "haldr" % "0.5"
import spray.json._
import DefaultJsonProtocol._
import haldr._

API

Resource class acts as a hal builder. Main methods are link and embed. There is support for uri templates. You still have to provide JsonProtocol for your domain classes. Additional uri properties may be added with prop method on links. It's still possible to have String or spray's Path link with props.

URIs

There are 3 string interpolators at your service:

  • u - absolute uri
  • r - relative uri (relative to parent resource uri)
  • t - absolute uri template; checks for RFC 6570) compliance

It possible to append path parts to uris with /.

Simple resource

Use u and r interpolation for DRY links

Resource(
  Customer("[email protected]"), u"/customers/deadbeaf")
   .link("books", u"/customers/deadbeaf/books")
   .link("files", u"/customers/deadbeaf/files")
Resource(
  Customer("[email protected]"), u"/customers/deadbeaf")
  .link("books", r"/books")
  .link("files", r"/files")
{
   "email": "[email protected]",
   "_links": {
      "self": {"href": "/customers/deadbeaf"},
      "books": {"href": "/customers/deadbeaf/books"},
      "files": {"href": "/customers/deadbeaf/files"}
   }
}

Link properties

Use prop on u, r, t or String.

Resource(
  Customer("[email protected]"),
    u"/customers/deadbeaf"
      .prop("name", "John Doe")
      .prop("title", "Dear customer"))
{
   "email": "[email protected]",
   "_links": {
      "self": {
          "href": "/customers/deadbeaf",
          "name": "John Doe",
          "title": "Dear customer"
      }
   }
}

Uri template

Resource(Map("email" -> "[email protected]"), u"/customers/deadbeaf")
  .link("search-by-name", t"/customers?name={name}")
{
   "email": "[email protected]",
   "_links": {
      "self": {"href": "/customers/deadbeaf"},
      "by-name": {
          "href": "/customers?name={name}",
          "templated": true
      }
   }
}

Embedding resource property

Resource(
  Customer("[email protected]"), u"/customers/deadbeaf")
  .embed("car", Vehicle("BMW", "i3"))
{
  "email": "[email protected]",
  "_embedded": {
     "car": {
        "make": "BMW",
        "model": "i3"
     }
  },
  "_links": {
     "self": {"href": "/customers/deadbeaf"}
  }
}

Embedding related resource

Resource(Customer("[email protected]"), u"/customers/deadbeaf")
  .embed("car", Resource(Car("BMW", "i3"), u"/customers/deadbeaf/cars/bmw_i3"))
  .link("books", u"/customers/deadbeaf/books")
{
  "email": "[email protected]",
  "_embedded": {
     "car": {
        "make": "BMW",
        "model": "i3",
        "_links": {
           "self": {"href": "/customers/deadbeaf/cars/bmw_i3"}
        }
     }
  },
  "_links": {
     "self": {"href": "/customers/deadbeaf"},
     "books": {"href": "/customers/deadbeaf/books"}
  }
}

Multilevel embedding with relative links

embed inside another embed with relative links.

Resource(Customer("[email protected]"), u"/customers/deadbeaf")
  .embed("addressHistory",
    Resource(Address("Argonautenstraat", 3), r"/address/1")
      .link("business", r"/business")
      .embed("locations", Resource(Location(10.0, 12.0), r"/location")
        .link("hide", r"/hide") :: Nil) :: Nil)
{
  "email": "[email protected]",
  "_embedded": {
     "addressHistory": [{
        "street": "Argonautenstraat",
        "house": 3,
        "_embedded": {
            "locations": [{
               "lng": 10.0,
               "lat": 12.0,
               "_links": {
                   "self": { "href" : "/customers/deadbeaf/address/1/location"},
                   "hide": { "href" : "/customers/deadbeaf/address/1/location/hide"}
               }
             }]
        },
        "_links": {
           "self": {"href": "/customers/deadbeaf/address/1"},
           "business": {"href": "/customers/deadbeaf/address/1/business"}
        }
     }]
  },
  "_links": {
      "self":   {"href": "/customers/deadbeaf"}
  }
}

URL encoding

u, r and spray's Path parts are encoded, when String is lifted to spray's Path type. One important thing to know, is when your path segment contains '/' - correct way to have it encoded is following:

u"/books" / "Slash / book"
"/books/Slash%20%2F%20book"

otherwise / will be parsed as path separator.

URL template encoding

Put the part into string interpolator arguments, like this:

val book = "Slash / book"
Resource(Map("email" -> "[email protected]"), u"/customers/deadbeaf")
  .link("book", t"/books/$book{?format}")
{
   "email": "[email protected]",
   "_links": {
      "self": {"href": "/customers/deadbeaf"},
      "book": {
          "href": "/books/Slash%20%2F%20book?{format}",
          "templated": true
       }
    }
}

Versions

Version
0.5