• Stars
    star
    13
  • Rank 1,460,484 (Top 30 %)
  • Language
    Scala
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A scala library for flexible JSON interfaces

lasic Build Status

Lasic is a small Scala library that allows you to generate JSON serialization on the fly. If you're coming from a functional background, lasic may make more sense described as "runtime lenses converted to JSON". Rather than having to write separate APIs to return different fields of the same object, lasic allows the UI (or anyone else) to request both the fields and pagination they want. It's also completely type safe, verified at compile time, and doesn't use reflection. Here's a quick example:

case class User(name: String, bio: String, email: String)
def allUsers: List[User]

Suppose users had really prolific bios and you didn't want to send them to the UI when the UI only wanted the user's name. Rather than needing to create a separate endpoint, lasic defines a simple query language to allow the UI to request exactly the fields it wants:

// Just the name an email, no bio
[name,email]

It also includes control for pagination:

// Get the name and email for up to 10 users, starting at the 5th
[name,email]*10+5

With these queries, lasic will generate the specific JSON requested by the UI with almost no boilerplate.

Quick Start

Add lasic as a dependency:

  • For SBT:
libraryDependencies += "com.github.rcoh" % "lasic_2.11" % "0.2.0"
  • For Maven:
<dependency>
  <groupId>com.github.rcoh</groupId>
  <artifactId>lasic_2.11</artifactId>
  <version>0.2.0</version>
</dependency>

Take your class:

case class User(name: String, email: String, bio: String, friends: List[Friend], internalId: Int)

Annotate the fields you want to expose to the UI:

import com.github.rcoh.query.loaders.{Expose, ExposeAlways, Loadable}
case class User(@Expose name: String, @ExposeAlways email: String, @Expose bio: String, @Expose friends: List[User], internalId: Int)

Generate Loadable[User]:

implicit val userLoadable = Loadable.byAnnotations[User]

Render some Json:

import com.github.rcoh.query.lang.QueryParser
import com.github.rcoh.query.render.Renderer
// Get the users name, email, and the name of their first 5 friends
val user: User = User("Alice", "[email protected]", "My bio", List(User("bob", "[email protected]",  "bob", List(), internalId = 0)), internalId = 1)
// In reality, you'd want to handle the possibility of a ParseError
val query = QueryParser.parse("[name,friends[name]*5]").right.get

import org.json4s.native.JsonMethods._
println(pretty(render(Renderer.render(user, query))))
/*
{
  "name":"Alice",
  "email":"[email protected]",
  "friends":[{
    "name":"bob",
    "email":"[email protected]"
  }]
}
*/

The email field appears even though we didn't request it because it's set to ExposeAlways. Note how the renderer properly handles the fact that friends is a list and correctly extracts fields.

But wait: there's more!

  • For cases where you want all the fields:
// As if you put `@ExposeAlways` on each field (not method!!)
implicit val allFieldsLoader = Loadable.allFieldsAlways[User]

// As if you put `@Expose` on each field
implicit val byRequest = Loadable.allFieldsByRequest[User]
  • Lasic also works for traits, normal classes, and objects. It even works if the annotated fields come from different places:
trait Entity {
   @ExposeAlways
   def id: String
}

trait UserEntity extends Entity {
   @Expose
   def email: String
   
   @Expose
   def age: Int
}

General Usage

In general, you'll want to wire up the rendering layer wherever in your webserver you are converting things to JSON to avoid code duplication. The only requirement is that the argument to the render method must be a member of the Loadable typeclass (def foo[A: Loadable](a: A))

Under the Hood

Lasic uses macros to build accesors for fields marked with @Expose and @ExposeAlways. The macro brings classes into the type class Loadable[T]. The macro also verifies that all exposed members of a given class are also Loadable[T]. Given a Loadable[T] the renderer parses the query string and builds the JSON object.

More Repositories

1

angle-grinder

Slice and dice logs on the command line
Rust
2,885
star
2

stacksmash

A collection of toy programs for teaching buffer overflow vulnerabilities.
Assembly
55
star
3

treelayout

Demonstrating the importance of laying out data in memory.
Go
47
star
4

toyregex

A Toy Regex Engine In Scala
Scala
36
star
5

tracing-texray

Tracing layer to quickly inspect spans and events
Rust
34
star
6

SmootLight

Modular Control System for Interactive Large Scale Pixel-Based Light Installations
Python
18
star
7

Burton-Conner-Tetris-Battle

Burton Conner Tetris Battle -- A Tetris Installation Controlled by DDR Pads on the Side of Burton Conner
Python
12
star
8

rust-brew-template

Brew Recipes for Rust CLI Apps
Ruby
7
star
9

rcoh-dot-me-v2

Personal site + blog rev2
TeX
6
star
10

gradsearch

gradsearch (re:search) is a website to connect students with professors who study their research interests.
PHP
5
star
11

auto-invoice

Automatically create Xero invoices from Toggl, then email them
Python
4
star
12

Rally

A lightweight chat client and protocol designed for reliability on unreliable connections
Python
3
star
13

electorate

A Simple Election Forecasting Model
Scala
2
star
14

trails

Python
2
star
15

modata

A work in progress...
Go
2
star
16

ipa-reader

Chrome Extension / Server to add a button to read IPA outloud
JavaScript
2
star
17

6.035

Assorted code for 6.035
Java
2
star
18

inyo

...
HTML
1
star
19

batmon

Battery notifications for people dumb enough to use xmonad ;-)
Python
1
star
20

Smart-Mailer

Dynamic Email List Creation for MIT Moira Lists
Python
1
star
21

sharing-is-caring

A Distributed Memory System for Linux
C
1
star
22

terminal-watcher

Monitor your terminal from your phone
Go
1
star
23

xw-tools-bugs

Crossword.Tools bug tracker & roadmap
1
star
24

todo

The TODO app I always wanted (a work in progress)
JavaScript
1
star
25

async-puzzlers

Various Rust Async Antipatterns and puzzles
Rust
1
star