gdstruct - GDS - General Data Structure

A General Data Structure (GDS) is a universal, composable data structure, used to store any kind of data.
This could be for example the definition of configurations, specifications and data sets. Typical usage is the definition of configurations, specifications and data sets. The GDS language is a special DSL (domain specific language) for defining general data structures. It uses a succinct, indentation-sensitive syntax which makes data representation clear and readable. The building blocks for general data structures are hashes and arrays.

Installation

gem install gdstruct

A Short Example

require "gdstruct"

h = GDstruct.c( <<-EOS )
a val a
b val b
EOS

# => h = { a: 'val a', b: 'val b' }

An Introduction

The GDS language uses two basic symbols (: and ,) for the creation of hashes and arrays.

A colon (:) is used to define a hash.
A comma (,) is used to define an array.

Use indentation with two spaces for the definition of elements and for nested structures. Tab characters are not allowed for indentation.

Another Example

caption foo
credit  bar
images
  small
    url  http://mywebsite.com/image-small.jpg
    dimensions
      height 500
      width  500
  large
    url  http://mywebsite.com/image-large.jpg
    dimensions
      height 500
      width  500
videos
  small
    preview  http://mywebsite.com/video.m4v
    dimensions
      height 300
      width  400

transforms to

{
  :caption => 'foo',
  :credit => 'bar',
  :images => {
    :small => {
      :url => 'http://mywebsite.com/image-small.jpg',
      :dimensions => {
        :height => 500,
        :width => 500
      }
    },
    :large => {
      :url => 'http://mywebsite.com/image-large.jpg',
      :dimensions => {
        :height => 500,
        :width => 500
      }
    },
  },
  :videos => {
    :small => {
      :preview => 'http://mywebsite.com/video.m4v',
      :dimensions => {
        :height => 300,
        :width => 400
      }
    }
  }
}

General Example

,
  v1
  : k2 v2
  : k31 v31 | k32 v32 | k33 v33
    k34 v34
    k35 v35 | k36 v36 
  : 
    k41 v41
    k42 v42
    k43,
    k44, 1 | 2 | 3
      4 | 5
      6
      7
      8 | 9
      :k441 v441
  v5

# =>  [ 'v1', { k2: 'v2' }, { k31: 'v31', k32: 'v32', k33: 'v33', k34: 'v34', k35: 'v35', k36: 'v36' }, 
        { k41: 'v41', k42: 'v42', k43: [], k44: [1, 2, 3, 4, 5, 6, 7, 8, 9, { k441: 'v441' } ] }, 'v5' ] 

Motivation and Features

  • the focus is on the essential data
  • structure and hierarchy is expressed using indentation (whitespace-sensitive) - avoids curly braces and square brackets
  • uses a succinct and minimalist syntax - tries to avoid unnecessary characters
  • in many cases colons, commas and quotes are not necessary
  • less text makes data clearer and more readable
  • for configuration and specification - replacement for XML, JSON, YAML
  • for data/database seeding
  • less text and less potential errors using schema definitions
  • supports block comments, which could be nested
  • allows also the definition of hash and array structures in a kind of restricted classic Ruby like syntax
  • provides an alternative for Ruby hash and array definition without using eval(); can be used as a protection against code injection vulnerabilities, e.g. on web servers

Schema specifiers

Schema specifiers can be used to predefine the keys of a hash or subhash. When you specify the values you no longer need to name the key for each value. This facilitates the input for hashes and prevents typos for keys.
In combination with the pipe symbol (|), which allows to define multiple values on a single line, this features a slim and clearly arranged, table-like style for data.

@schema country(name,capital,area,population,vehicleRegistrationCode,iso3166code,callingCode)
, @schema country   /*
    name            capital            area (km^2)   population      vehicleRegistrationCode   iso3166code   callingCode
  ---------------------------------------------------------------------------------------------------------------------------- */
  : Deutschland   | Berlin           |    357_385  |    82_521_653 | D                       | DE          | 49
  : USA           | Washington, D.C. |  9_833_520  |   325_719_178 | USA                     | US          | 1
  : China         | Beijing          |  9_596_961  | 1_403_500_365 | CHN                     | CN          | 86
  : India         | New Dehli        |  3_287_469  | 1_339_180_000 | IND                     | IN          | 91
  : Austria       | Vienna           |     83_878  |     8_822_267 | A                       | AT          | 43
  : Denmark       | Copenhagen       |     42_921  |     5_748_769 | DK                      | DK          | 45
  : Canada        | Ottawa           |  9_984_670  |    36_503_097 | CDN                     | CA          | 1
  : France        | Paris            |    643_801  |    66_991_000 | F                       | FR          | 33
  : Russia        | Moscow           | 17_075_400  |   144_526_636 | RUS                     | RU          | 7

transforms to

[
  { :name=>"Deutschland", :capital=>"Berlin", :area=>357385, :population=>82521653, :vehicleRegistrationCode=>"D", :iso3166code=>"DE", :callingCode=>49 },
  { :name=>"USA", :capital=>"Washington, D.C.", :area=>9833520, :population=>325719178, :vehicleRegistrationCode=>"USA", :iso3166code=>"US", :callingCode=>1 },
  { :name=>"China", :capital=>"Beijing", :area=>9596961, :population=>1403500365, :vehicleRegistrationCode=>"CHN", :iso3166code=>"CN", :callingCode=>86 },
  { :name=>"India", :capital=>"New Dehli", :area=>3287469, :population=>1339180000, :vehicleRegistrationCode=>"IND", :iso3166code=>"IN", :callingCode=>91 },
  { :name=>"Austria", :capital=>"Vienna", :area=>83878, :population=>8822267, :vehicleRegistrationCode=>"A", :iso3166code=>"AT", :callingCode=>43 },
  { :name=>"Denmark", :capital=>"Copenhagen", :area=>42921, :population=>5748769, :vehicleRegistrationCode=>"DK", :iso3166code=>"DK", :callingCode=>45 },
  { :name=>"Canada", :capital=>"Ottawa", :area=>9984670, :population=>36503097, :vehicleRegistrationCode=>"CDN", :iso3166code=>"CA", :callingCode=>1 },
  { :name=>"France", :capital=>"Paris", :area=>643801, :population=>66991000, :vehicleRegistrationCode=>"F", :iso3166code=>"FR", :callingCode=>33 },
  { :name=>"Russia", :capital=>"Moscow", :area=>17075400, :population=>144526636, :vehicleRegistrationCode=>"RUS", :iso3166code=>"RU", :callingCode=>7 }
] 

Further Information

You will find further information here: urasepandia.de/gds.html

Maintainer

Uli Ramminger [email protected]

Copyright

Copyright (c) 2018 Ulrich Ramminger

See MIT-LICENSE for further details.