json-schematized 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +3 -0
- data/Gemfile.lock +28 -0
- data/README.md +44 -0
- data/lib/json-schematized.rb +14 -0
- data/lib/json/schematized/base.rb +17 -0
- data/lib/json/schematized/builder.rb +77 -0
- data/lib/json/schematized/dsl.rb +22 -0
- data/lib/json/schematized_objects.rb +51 -0
- metadata +116 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
json-schematized (0.1.0)
|
5
|
+
multi_json (~> 1.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
json (1.7.5)
|
12
|
+
multi_json (1.5.0)
|
13
|
+
rspec (2.10.0)
|
14
|
+
rspec-core (~> 2.10.0)
|
15
|
+
rspec-expectations (~> 2.10.0)
|
16
|
+
rspec-mocks (~> 2.10.0)
|
17
|
+
rspec-core (2.10.1)
|
18
|
+
rspec-expectations (2.10.0)
|
19
|
+
diff-lcs (~> 1.1.3)
|
20
|
+
rspec-mocks (2.10.1)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
ruby
|
24
|
+
|
25
|
+
DEPENDENCIES
|
26
|
+
json (~> 1.4)
|
27
|
+
json-schematized!
|
28
|
+
rspec (>= 2.6)
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# JSON::Schematized
|
2
|
+
|
3
|
+
Template builder based on JSON-Schema.
|
4
|
+
|
5
|
+
## Sample usage
|
6
|
+
|
7
|
+
Consider the following JSON-Schema (escaped as YAML, for better viewing):
|
8
|
+
|
9
|
+
```yaml
|
10
|
+
# person.yml
|
11
|
+
person:
|
12
|
+
name:
|
13
|
+
type: string
|
14
|
+
birth:
|
15
|
+
type: object
|
16
|
+
properties:
|
17
|
+
name:
|
18
|
+
type: string
|
19
|
+
children:
|
20
|
+
type: array
|
21
|
+
required: true
|
22
|
+
items:
|
23
|
+
type: object
|
24
|
+
properties:
|
25
|
+
name:
|
26
|
+
type: string
|
27
|
+
```
|
28
|
+
|
29
|
+
Usage:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require "json-schematized"
|
33
|
+
|
34
|
+
class Person < JSON::Schematized::Base
|
35
|
+
json_schema do # block called for each new instance
|
36
|
+
YAML.load(File.read(File.expand_path("../person.yml", __FILE__)))["person"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
person = Person.new name: "John", birth: {name: "John Smith"}
|
41
|
+
person.children # => []
|
42
|
+
person.name # => "John"
|
43
|
+
person.birth.name # => "John Smith"
|
44
|
+
```
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
|
6
|
+
module JSON
|
7
|
+
module Schematized
|
8
|
+
autoload :Base, "json/schematized/base"
|
9
|
+
autoload :Builder, "json/schematized/builder"
|
10
|
+
autoload :DSL, "json/schematized/dsl"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require "json/schematized_objects"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module JSON
|
3
|
+
module Schematized
|
4
|
+
class Base
|
5
|
+
extend DSL
|
6
|
+
include SchematizedObject
|
7
|
+
|
8
|
+
attr_reader :__json__
|
9
|
+
|
10
|
+
def initialize(attrs = nil)
|
11
|
+
@__json__ = {}
|
12
|
+
@__schema__ = Builder.new(self.class.json_schema)
|
13
|
+
__schema__.copy_to(__json__, attrs)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module JSON
|
3
|
+
module Schematized
|
4
|
+
class Builder
|
5
|
+
attr_reader :schema
|
6
|
+
|
7
|
+
def initialize(schema)
|
8
|
+
@schema = schema
|
9
|
+
end
|
10
|
+
|
11
|
+
def member?(key)
|
12
|
+
schema[:properties][key.to_sym]
|
13
|
+
end
|
14
|
+
|
15
|
+
def copy_to(json, attrs)
|
16
|
+
if json.is_a?(Array)
|
17
|
+
return unless attrs.is_a?(Array)
|
18
|
+
attrs.each{ |value| assign!(json, nil, schema, value) }
|
19
|
+
else
|
20
|
+
return unless attrs.is_a?(Hash)
|
21
|
+
attrs.each_pair do |key, value|
|
22
|
+
meta = member?(key)
|
23
|
+
assign!(json, key, meta, value) if meta
|
24
|
+
end
|
25
|
+
end
|
26
|
+
ensure_structure(json, schema)
|
27
|
+
json
|
28
|
+
end
|
29
|
+
|
30
|
+
def ensure_structure(json, schema)
|
31
|
+
case json
|
32
|
+
when Array
|
33
|
+
meta = schema[:items]
|
34
|
+
case meta && meta[:type]
|
35
|
+
when "object", "array"
|
36
|
+
json.each do |value|
|
37
|
+
ensure_structure(value, meta)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
when Hash
|
41
|
+
meta = schema[:properties]
|
42
|
+
meta.each_pair do |key, schema|
|
43
|
+
case value = json[key.to_s]
|
44
|
+
when Hash
|
45
|
+
ensure_structure(value, schema) if schema[:type] == "object"
|
46
|
+
when Array
|
47
|
+
ensure_structure(value, schema) if schema[:type] == "array"
|
48
|
+
when nil
|
49
|
+
if schema[:required]
|
50
|
+
case schema[:type]
|
51
|
+
when "object"
|
52
|
+
ensure_structure(json[key.to_s] = {}, schema)
|
53
|
+
when "array"
|
54
|
+
ensure_structure(json[key.to_s] = [], schema)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def assign!(json, key, meta, value)
|
63
|
+
case meta[:type]
|
64
|
+
when "object"
|
65
|
+
value = self.class.new(meta).copy_to({}, value)
|
66
|
+
when "array"
|
67
|
+
value = self.class.new(meta[:items]).copy_to([], value)
|
68
|
+
end
|
69
|
+
if json.is_a?(Array)
|
70
|
+
json << value
|
71
|
+
else
|
72
|
+
json[key.to_s] = value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require "multi_json"
|
4
|
+
|
5
|
+
module JSON
|
6
|
+
module Schematized
|
7
|
+
module DSL
|
8
|
+
def json_schema(json = nil, &block)
|
9
|
+
if instance_variable_defined?(:"@json_schema")
|
10
|
+
schema = @json_schema[:loader].call
|
11
|
+
schema = MultiJson.dump(schema) unless schema.is_a?(String)
|
12
|
+
MultiJson.load(schema, :symbolize_keys => true)
|
13
|
+
else
|
14
|
+
return if self === Base
|
15
|
+
raise ArgumentError, "JSON or block expected" if block_given? ^ json.nil?
|
16
|
+
block = Proc.new{ json } unless block_given?
|
17
|
+
@json_schema = {:loader => block}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module JSON
|
3
|
+
module SchematizedObject
|
4
|
+
attr_accessor :__schema__
|
5
|
+
|
6
|
+
def __json__
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def method_missing(name, *args)
|
13
|
+
key = name.to_s
|
14
|
+
if key =~ /=\z/
|
15
|
+
key = $`.to_sym
|
16
|
+
meta = __schema__.member?(key)
|
17
|
+
meta ? __schema__.assign!(__json__, key, meta, args.first) : super
|
18
|
+
else
|
19
|
+
read_attribute key
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def read_attribute(name)
|
24
|
+
name = name.to_s
|
25
|
+
value = __json__[name]
|
26
|
+
if !__json__.has_key?(name) && (meta = __schema__.member?(name))
|
27
|
+
case meta[:type]
|
28
|
+
when "array"
|
29
|
+
value = __json__[name] = [].tap do |array|
|
30
|
+
array.extend SchematizedArray
|
31
|
+
array.__schema__ = __schema__.class.new(meta[:items])
|
32
|
+
end
|
33
|
+
when "object"
|
34
|
+
value = __json__[name] = {}.tap do |hash|
|
35
|
+
hash.extend SchematizedObject
|
36
|
+
hash.__schema__ = __schema__.class.new(meta)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module SchematizedArray
|
45
|
+
attr_accessor :__schema__
|
46
|
+
|
47
|
+
def __json__
|
48
|
+
self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: json-schematized
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Marcelo Manzan
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-01-15 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: multi_json
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 15
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 0
|
32
|
+
version: "1.0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: json
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 7
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 4
|
47
|
+
version: "1.4"
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rspec
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 15
|
59
|
+
segments:
|
60
|
+
- 2
|
61
|
+
- 6
|
62
|
+
version: "2.6"
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
description: ""
|
66
|
+
email: manzan@gmail.com
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files: []
|
72
|
+
|
73
|
+
files:
|
74
|
+
- lib/json/schematized/base.rb
|
75
|
+
- lib/json/schematized/builder.rb
|
76
|
+
- lib/json/schematized/dsl.rb
|
77
|
+
- lib/json/schematized_objects.rb
|
78
|
+
- lib/json-schematized.rb
|
79
|
+
- README.md
|
80
|
+
- Gemfile
|
81
|
+
- Gemfile.lock
|
82
|
+
homepage: http://github.com/abril
|
83
|
+
licenses: []
|
84
|
+
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
hash: 3
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
hash: 3
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 1.8.15
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Template builder based on JSON-Schema
|
115
|
+
test_files: []
|
116
|
+
|