An open API service indexing awesome lists of open source software.

https://github.com/andyw8/motion-json-decoder

Treat JSON nodes as rich objects.
https://github.com/andyw8/motion-json-decoder

Last synced: about 1 month ago
JSON representation

Treat JSON nodes as rich objects.

Awesome Lists containing this project

README

        

motion-json-decoder
===================

Treat a parsed JSON response as a graph of proper Ruby objects, rather than plain hashes and arrays.

Installation
------------
* Add `motion-json-decoder` to your Gemfile and run `bundle`.
* Add `require 'motion-json-decoder` to your Rakefile.

Basic Example
-------------

Let's say you have a RubyMotion app which parses this response from the server:

{
"people":
[
{
"first_name": "John",
"last_name": "Smith",
"date_of_birth": "1980-01-03"
},
{
"first_name": "Joe",
"last_name": "Bloggs",
"date_of_birth": "1967-10-11"
}
]
}

i.e. a *people* collection which contains two *person* nodes.

There may be a number of place in your app where you want to display a person's full name:

names = []
json['people'].each do |person|
full_name = person['first_name'] + ' ' + person['last_name']
names << full_name
end

But doing this in multiply places isn't very DRY. You could write a helper method, but where should that code live?

*motion-json-decoder* allows the creation of mappings between the nodes in a JSON response, and simple objects. Just include the module in your class and use the simple DSL to declare your fields:

class Person
include JSONDecoder::Node

field :first_name
field :last_name

def full_name
first_name + ' ' + last_name
end
end

You can then treat person as a simple object, by passing a hash when instantiating a new node object:

names = []
json['people'].each do |person_hash|
person = Person.new(person_hash)
NSLog "Adding #{person.first_name}..."
names << person.full_name
end

Extra Protection
----------------

Under the hood, motion-json-decoder uses `Hash#fetch` rather than `Hash#[]`, so if you call a field which doesn't exist, you'll get an exception right away, rather than a potentially difficult-to-debug nil return value.

Checking for Presence
---------------------
You can check if the node contains a particular key:

class Person
include JSONDecoder::Node

field :first_name
field :last_name
field :middle_name
end

person = Person.new({'first_name' => 'Andy', 'last_name' => nil})
person.first_name? #-> true
person.last_name? #-> true (even though it's nil)
person.middle_name? #-> false

Collections
------------

You can specify that a nodes contains a collection of other 'resources' rather than a simple literals:

collection :organisations, :class_name -> { Organisation }

class_name parameter should be another class which includes the `JSONDecoder::Node` module.

When you call json.people, rather than array of hashes, you'll get an array of Organisation objects.

The use of the lambda (`->`) is to avoid dependency resolution problems at compile time.