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 ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -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)
@@ -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
+