SURF Quick Start

JSON

SURF is simple, like JSON. In fact all JSON documents are also SURF documents. Here is a typical JSON document that is valid SURF—but SURF provides many improvements.

User information serialized in JSON.
{
  "authenticated" : true,
  "sort" : "d",
  "name" : "Jane Doe",
  "id" : "bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832",
  "email" : "jane_doe@example.com",
  "phone" : "+12015550123",
  "usernames" : ["jdoe", "janed"],
  "homePage" : "http://www.example.com/jdoe/",
  "salt" : "Zm9vYmFy",
  "joined" : "2016-01-23",
  "credits" : 123
}

Dates

Why should you have to add another layer of programming to parse and serialize dates manually? SURF includes dates out of the box: timestamps, dates, times, time zones, “local” dates/times, birthdays, durations—you name it!

Ditch the string type and add an initial at-sign @ symbol for real dates in SURF.

One of many SURF date types.
{
  "authenticated" : true,
  "sort" : "d",
  "name" : "Jane Doe",
  "id" : "bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832",
  "email" : "jane_doe@example.com",
  "phone" : "+12015550123",
  "usernames" : ["jdoe", "janed"],
  "homePage" : "http://www.example.com/jdoe/",
  "salt" : "Zm9vYmFy",
  "joined" : @2016-01-23,
  "credits" : 123
}

More Types… and Comments

Characters, IRIs, UUIDs, email addresses, telephone numbers, binary values—all those are included, and more.

You might have forgotten to ask for comments, since JSON doesn't have them. SURF supports them with the exclamation ! mark.

SURF literals and comments.
{
  "authenticated" : true,
  "sort" : 'd', !character literal
  "name" : "Jane Doe"
  "id" : &bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832, !UUID literal
  "email" : ^jane_doe@example.com, !email address literal
  "phone" : +12015550123, !telephone number literal
  "usernames" : ["jdoe", "janed"],
  "homePage" : <http://www.example.com/jdoe/>, !IRI literal
  "salt" : %Zm9vYmFy, !binary literal
  "joined" : @2016-01-23,
  "credits" : 123
}

Human Friendly

How many times have you left out a comma in JSON? In SURF you don't need them when newlines are present. You're still free to use commas if you want a compact, almost binary-like SURF document with no whitespace.

SURF without commas.
{
  "authenticated" : true
  "sort" : 'd'
  "name" : "Jane Doe"
  "id" : &bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832
  "email" : ^jane_doe@example.com
  "phone" : +12015550123
  "usernames" : [
    "jdoe"
    "janed"
  ]
  "homePage" : <http://www.example.com/jdoe/>
  "salt" : %Zm9vYmFy
  "joined" : @2016-01-23,
  "credits" : 123
}

Objects

Did you think you were describing an object representing a user? JSON is a bit sly: you were really defining a JSON “associative array” or map.

SURF allows you to use identifiers to describe semantic property relationships to real object instances, denoted by the asterisk * character. You can even specify the object type!

Ditch the JSON map key quotes and upgrade to SURF objects. SURF objects use the equal = character for property assignments. The object type User in the example is optional, but really helpful if you want to indicate the type of a real object!

SURF objects.
*User:
  authenticated = true
  sort = 'd'
  name = "Jane Doe"
  id = &bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832
  email = ^jane_doe@example.com
  phone = +12015550123
  usernames = [
    "jdoe"
    "janed"
  ]
  homePage = <http://www.example.com/jdoe/>
  salt = %Zm9vYmFy
  joined = @2016-01-23,
  credits = 123
;

Collections

You want maps anyway? You can have them! SURF maps don't restrict your map property keys to strings like JSON does. In addition to maps (backwards-compatible with JSON) and lists (compatible with JSON arrays), SURF also has sets.

Your programming language probably has all three of these collection types, so why shouldn't your serialization format?

SURF collections.
*User:
  authenticated = true
  sort = 'd'
  name = "Jane Doe"
  id = &bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832
  email = ^jane_doe@example.com
  phone = +12015550123
      !the usernames have no order, so here a set
      !has more appropriate semantics than a list
  usernames = (
    "jdoe"
    "janed"
  )
  homePage = <http://www.example.com/jdoe/>
  salt = %Zm9vYmFy
  joined = @2016-01-23,
  credits = 123
  favoriteThings = {
    5 : "Users's favorite number." !a map can have keys of any type
    "aliquot" : "Users's favorite word."
  }
  !the list of colors said to make up the spectrum of a rainbow, in order
  rainbow = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
;

Labels

Your id property is working just fine, but you are the only one who knows that the “id” value is used as your object's primary identifier. Why not encode that knowledge into the SURF document?

SURF allows you to declare a global identifier called a tag for each object. Place any IRI you choose between vertical line | characters. For short you can use |<&bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832>|; it means the same thing as |<urn:uuid:bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832>|. After declaring a tag in front of the initial object description, you can place that tag anywhere the original object would have appeared to form graph references.

If an object doesn't have a primary identifier, you can declare an alias by using any valid SURF name instead of an IRI, for example |fooBar|. Aliases are syntax-only; they are not part of the defined object, and only exist within the SURF serialization. Tags and aliases are collectively referred to as labels in the SURF syntax.

SURF object IRI identifier tags.
*Config:
  users = [
    |<urn:uuid:bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832>|*User:
      name = "Jane Doe"
    ;
    |<urn:uuid:d5207ff8-f64e-46b9-8fd9-d84ce8e0ff29>|*User:
      name = "John Doe"
    ;
  ]
  winner = |<urn:uuid:bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832>|
;

Semantic Framework

SURF is not an arbitrary syntax; it is built on top of a semantic model named the Uniform Resource Framework (URF). Every piece of data in SURF is an URF resource which can be described. In URF even properties are resources which can be described by their own properties. SURF literals also represent resources that in URF have IRIs. If processed by an URF processor, a SURF document becomes a set of logical propositions related to the identified resources, allowing reasoning engines to make inferences to produce answers to new questions related to existing data sets. URF is like Resource Description Framework (RDF), if RDF were simple and consistent.

But you don't need to know anything about semantic frameworks in order to use SURF. You can just use SURF as a better JSON. Under the covers SURF hides a rigorous semantic description of your data, should you ever want to use it. But if you dont need it, you'll never know it's there. That's what puts the “simple” in Simple URF (SURF).

Learn more.

There are more features and types available in SURF, but it doesn't get much more difficult than what you've seen here. SURF keeps it simple.

You can learn more about SURF and serialization formats in general, as well as read the SURF specification.