json-schematized 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+