Announcing GRFON, a kinder, gentler serialization format

For our High Frontier video game, we wanted a data file format that would be easy for people to read and write.  This is partly for our own use — we would be hand-editing files defining various parts of the game internally — and partly for mod authors, who would be creating new content for the game.

The big players in the serialization space are JSON and XML.  XML is, to be blunt, horrible.  It's fine for data that is only ever looked at by computer programs, but for anything that might be read or written by a human, it's just awful.  JSON is much better, and it's what we've often used in the past.  But it too has more syntax than feels necessary.  And at the same time, it lacks some features we really wanted, like comments.

So we have designed a new serialization format: GRFON (General Recursive Format Object Notation).  We've been using it for over a year now, and loving every minute of it.  And today, we are making it available for everyone else to use too, under the permissive MIT open-source license.

 

Our design goals with GRFON:

  • easy to read — minimal syntax to get in your way
  • easy to write — minimal syntax to screw up
  • comments, for all the same reasons comments in source code are a Good Thing
  • easy to use in a project

Let's illustrate with a couple of examples.  These are taken from the JSON Example web page, so they are of course selected to make JSON look good.  But let's see how they compare to GRFON.

Example 1 (JSON):

{"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}

Example 1 (XML):

<menu id="file" value="File">
  <popup>
    <menuitem value="New" onclick="CreateNewDoc()" />
    <menuitem value="Open" onclick="OpenDoc()" />
    <menuitem value="Close" onclick="CloseDoc()" />
  </popup>
</menu>

Example 1 (GRFON):

// This defines the standard File menu.  (Hey look, a comment!)
menu: {
    id: file     // (unique internal identifier)
    value: File
    popup: {
        {value: New; onclick: CreateNewDoc() }
        {value: Open; onclick: OpenDoc() }
        {value: Close; onclick: CloseDoc() }
  }
}

You can see here that the GRFON version has very little extra cruft; mostly curly braces for grouping things, and semicolons for separating things only if they're on the same line.  Items can also be separated by a line break, and the above example shows both styles.  This example also shows comments, both on a line by itself, and at the end of a line after some data.

Example 2 (JSON):

{
    "glossary": {
        "title": "example glossary",
		"GlossDiv": {
            "title": "S",
			"GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
					"SortAs": "SGML",
					"GlossTerm": "Standard Generalized Markup Language",
					"Acronym": "SGML",
					"Abbrev": "ISO 8879:1986",
					"GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
						"GlossSeeAlso": ["GML", "XML"]
                    },
					"GlossSee": "markup"
                }
            }
        }
    }
}

Example 2 (XML):

<!DOCTYPE glossary PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
 <glossary><title>example glossary</title>
  <GlossDiv><title>S</title>
   <GlossList>
    <GlossEntry ID="SGML" SortAs="SGML">
     <GlossTerm>Standard Generalized Markup Language</GlossTerm>
     <Acronym>SGML</Acronym>
     <Abbrev>ISO 8879:1986</Abbrev>
     <GlossDef>
      <para>A meta-markup language, used to create markup
languages such as DocBook.</para>
      <GlossSeeAlso OtherTerm="GML">
      <GlossSeeAlso OtherTerm="XML">
     </GlossDef>
     <GlossSee OtherTerm="markup">
    </GlossEntry>
   </GlossList>
  </GlossDiv>
 </glossary>

Example 2 (GRFON):

// We've omitted the top-level grouping this time because,
// in GRFON, you don't need it!
title: example glossary
GlossDiv: {
	title: S
	GlossList: {
		GlossEntry: {
			ID: SGML
			SortAs: SGML
			GlossTerm: Standard Generalized Markup Language
			Acronym: SGML
			Abbrev: ISO 8879:1986
			GlossDef: {
				para: A meta-markup language, used to create markup languages such as DocBook.
				GlossSeeAlso: { GML; XML }
			}
			GlossSee: markup
		}
	}
}

Again we see the GRFON version is just simpler.  We believe that computers should work hard for us, not the other way around!

You can find more examples on the GRFON Wiki, which is also where you'll find all the documentation for writing GRFON or adding GRFON to your own project.

GRFON is currently implemented as a C# source file.  We use it with Unity, but it should work in any C# environment.  Additional implementations in other languages may be added in the future.

We've found GRFON to be a real pleasure to use, and I hope others will find it useful too.