json2ruby 0.1.0 → 0.1.1
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/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +10 -2
- data/lib/json2ruby/attribute.rb +12 -1
- data/lib/json2ruby/cli.rb +8 -1
- data/lib/json2ruby/collection.rb +18 -1
- data/lib/json2ruby/entity.rb +26 -2
- data/lib/json2ruby/primitive.rb +16 -7
- data/lib/json2ruby/ruby_writer.rb +17 -1
- data/lib/json2ruby/version.rb +3 -1
- data/spec/collection_spec.rb +2 -2
- data/spec/entity_spec.rb +1 -1
- data/spec/primitive_spec.rb +1 -1
- metadata +3 -2
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# json2ruby
|
2
2
|
|
3
|
-
[](https://travis-ci.org/tomdionysus/json2ruby) [](https://coveralls.io/github/tomdionysus/json2ruby?branch=master)
|
3
|
+
[](https://travis-ci.org/tomdionysus/json2ruby) [](https://coveralls.io/github/tomdionysus/json2ruby?branch=master) [](http://badge.fury.io/rb/json2ruby)
|
4
4
|
|
5
5
|
A ruby rool for generating POROs from JSON data. It is intended to generate ruby model classes/modules from existing JSON data, e.g. responses from an API.
|
6
6
|
|
@@ -11,7 +11,7 @@ The tool will 'fold down' objects with identical fields - i.e. if an object has
|
|
11
11
|
## Installation
|
12
12
|
|
13
13
|
```bash
|
14
|
-
|
14
|
+
gem install json2ruby
|
15
15
|
```
|
16
16
|
|
17
17
|
## Usage
|
@@ -69,6 +69,14 @@ end
|
|
69
69
|
|
70
70
|
The option `-N, --forcenumeric` can be useful to fold down identical types where an attribute which is a float happens to have an integer value, to avoid generating two identical types.
|
71
71
|
|
72
|
+
## Documentation
|
73
|
+
|
74
|
+
Regenerate the documentation with 'rdoc':
|
75
|
+
|
76
|
+
```bash
|
77
|
+
rdoc
|
78
|
+
```
|
79
|
+
|
72
80
|
## Contributing
|
73
81
|
|
74
82
|
1. Fork it
|
data/lib/json2ruby/attribute.rb
CHANGED
@@ -1,22 +1,33 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
|
3
3
|
module JSON2Ruby
|
4
|
+
# The Attribute class represents a field on an Entity - i.e. A field name and associated type.
|
4
5
|
class Attribute
|
5
|
-
|
6
|
+
# The String name of the Attribute
|
7
|
+
attr_accessor :name
|
8
|
+
# The original String name of the Array in the JSON ([^A-Za-z0-9_] are replaced with '_')
|
9
|
+
attr_accessor :original_name
|
10
|
+
# The type of the attribute, i.e. a Entity, Collection or Primitive instance
|
11
|
+
attr_accessor :ruby_type
|
6
12
|
|
13
|
+
# The short name is 'Attribute'
|
7
14
|
def self.short_name
|
8
15
|
"Attribute"
|
9
16
|
end
|
10
17
|
|
18
|
+
# Create a new attribute with the supplied String name and optional String type name.
|
19
|
+
# If the type is not supplied or nil, if will be assigned '_unknown'
|
11
20
|
def initialize(name, ruby_type = nil)
|
12
21
|
@name = name
|
13
22
|
@ruby_type = ruby_type || "_unknown"
|
14
23
|
end
|
15
24
|
|
25
|
+
# Return the MD5 hash of the name and the type.
|
16
26
|
def attr_hash
|
17
27
|
Digest::MD5.hexdigest("#{@name}:#{@ruby_type}")
|
18
28
|
end
|
19
29
|
|
30
|
+
# An Attribute is equal to another if and only if its attr_hash value is the same.
|
20
31
|
def ==(other)
|
21
32
|
return false if other.class != self.class
|
22
33
|
attr_hash == other.attr_hash
|
data/lib/json2ruby/cli.rb
CHANGED
@@ -4,7 +4,9 @@ require 'optparse'
|
|
4
4
|
|
5
5
|
module JSON2Ruby
|
6
6
|
|
7
|
+
# The CLI (Command Line Interface) functionality class for the json2ruby executable
|
7
8
|
class CLI
|
9
|
+
# Run the json2ruby command, using arguments in ARGV.
|
8
10
|
def self.run
|
9
11
|
|
10
12
|
puts "json2ruby v#{VERSION}\n"
|
@@ -26,6 +28,7 @@ module JSON2Ruby
|
|
26
28
|
write_files(rootclasses, writer, options)
|
27
29
|
end
|
28
30
|
|
31
|
+
# Create the output directory with the options[:outputdir] if it does not exist.
|
29
32
|
def self.ensure_output_dir(options)
|
30
33
|
puts "Output Directory: #{options[:outputdir]}" if options[:verbose]
|
31
34
|
unless Dir.exists?(options[:outputdir])
|
@@ -34,8 +37,8 @@ module JSON2Ruby
|
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
40
|
+
# Process ARGV for command line switches and return the options hash.
|
37
41
|
def self.get_cli_options
|
38
|
-
|
39
42
|
options = {}
|
40
43
|
OptionParser.new do |opts|
|
41
44
|
opts.banner = "Usage: #{$0} [options] <file.json> [<file.json>....]"
|
@@ -115,6 +118,7 @@ module JSON2Ruby
|
|
115
118
|
options
|
116
119
|
end
|
117
120
|
|
121
|
+
# Parse all JSON files in ARGV and build the Entity cache, using the supplied options Hash.
|
118
122
|
def self.parse_files(options)
|
119
123
|
# Reset the object cache
|
120
124
|
Entity.reset_parse
|
@@ -137,6 +141,8 @@ module JSON2Ruby
|
|
137
141
|
rootclasses
|
138
142
|
end
|
139
143
|
|
144
|
+
# Write out all types in the Entity cache, except primitives and those contained in the
|
145
|
+
# rootclasses array, to the provided writer with the supplied options Hash.
|
140
146
|
def self.write_files(rootclasses, writer, options)
|
141
147
|
files = 0
|
142
148
|
Entity.entities.each do |k,v|
|
@@ -171,6 +177,7 @@ module JSON2Ruby
|
|
171
177
|
puts "Done, Generated #{files} file#{files==1 ? '' : 's'}"
|
172
178
|
end
|
173
179
|
|
180
|
+
# Display the Entity supplied in ent with the supplied hash value hsh to STDOUT
|
174
181
|
def self.display_entity(hsh, ent)
|
175
182
|
puts "- #{ent.name} (#{ent.class.short_name} - #{hsh})"
|
176
183
|
if ent.is_a?(Entity)
|
data/lib/json2ruby/collection.rb
CHANGED
@@ -1,18 +1,31 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
|
3
3
|
module JSON2Ruby
|
4
|
+
# Collection represents a JSON Array
|
4
5
|
class Collection
|
5
|
-
|
6
|
+
# The String name of the Array, i.e. the field name in which it was first encountered.
|
7
|
+
attr_accessor :name
|
8
|
+
# The original String name of the Array in the JSON ([^A-Za-z0-9_] are replaced with '_')
|
9
|
+
attr_accessor :original_name
|
10
|
+
# The array of types (Entity, Collection or Primitive instances) encountered in the JSON Array
|
11
|
+
attr_accessor :ruby_types
|
6
12
|
|
13
|
+
# The short name is 'Collection'
|
7
14
|
def self.short_name
|
8
15
|
"Collection"
|
9
16
|
end
|
10
17
|
|
18
|
+
# Create a new Collection with the specified name and optional Array of ypes.
|
11
19
|
def initialize(name, ruby_types = {})
|
12
20
|
@name = name
|
13
21
|
@ruby_types = ruby_types
|
14
22
|
end
|
15
23
|
|
24
|
+
# Create a new, or return an existing, Collection named name that supports all types in obj_array.
|
25
|
+
# Optionally, options can be supplied:
|
26
|
+
# * :forcenumeric => true - Use RUBYNUMERIC instead of RUBYINTEGER / RUBYFLOAT.
|
27
|
+
#
|
28
|
+
# Note: Contained JSON Objects and Arrays will be recursively parsed into Entity and Collection instances.
|
16
29
|
def self.parse_from(name, obj_array, options = {})
|
17
30
|
ob = self.new(name)
|
18
31
|
obj_array.each do |v|
|
@@ -41,6 +54,8 @@ module JSON2Ruby
|
|
41
54
|
ob
|
42
55
|
end
|
43
56
|
|
57
|
+
# Return a 128-bit hash as a hex string, representative of the set of possible types in the Collection
|
58
|
+
# Internally, this is calculated as the MD5 hash of the attr_hash values of all types.
|
44
59
|
def attr_hash
|
45
60
|
md5 = Digest::MD5.new
|
46
61
|
@ruby_types.each do |k,typ|
|
@@ -49,11 +64,13 @@ module JSON2Ruby
|
|
49
64
|
md5.hexdigest
|
50
65
|
end
|
51
66
|
|
67
|
+
# Compare this Collection with another Collection. Two collections are equal if and only if they can contain exactly the same types.
|
52
68
|
def ==(other)
|
53
69
|
return false if other.class != self.class
|
54
70
|
attr_hash == other.attr_hash
|
55
71
|
end
|
56
72
|
|
73
|
+
# Generate a String comment of the form '<x>[] (<y)' where <x> and <y> are the name and original name of the Collection respectively.
|
57
74
|
def comment
|
58
75
|
x = "#{@name}[]"
|
59
76
|
x += " (#{@original_name})" unless @original_name.nil?
|
data/lib/json2ruby/entity.rb
CHANGED
@@ -1,19 +1,28 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
|
3
3
|
module JSON2Ruby
|
4
|
-
|
4
|
+
# Entity represents a JSON Object.
|
5
5
|
class Entity
|
6
|
-
|
6
|
+
# The String name of the Object - i.e. the field name in which it was first encountered.
|
7
|
+
attr_accessor :name
|
8
|
+
# The original String name of the object in the JSON ([^A-Za-z0-9_] are replaced with '_')
|
9
|
+
attr_accessor :original_name
|
10
|
+
# A Hash of String names to Attribute instances for this Entity, representing its attributes.
|
11
|
+
attr_accessor :attributes
|
7
12
|
|
13
|
+
# The short name is 'Entity'
|
8
14
|
def self.short_name
|
9
15
|
"Entity"
|
10
16
|
end
|
11
17
|
|
18
|
+
# Create a new Entity with the specified name and optional Hash of attributes (String name to Entity, Collection or Primitive instances)
|
12
19
|
def initialize(name, attributes = {})
|
13
20
|
@name = name
|
14
21
|
@attributes = attributes
|
15
22
|
end
|
16
23
|
|
24
|
+
# Return a 128-bit hash as a hex string, representative of the unique set of fields and their types, including all subobjects.
|
25
|
+
# Internally, this is calculated as the MD5 of all field names and their type attr_hash calls.
|
17
26
|
def attr_hash
|
18
27
|
md5 = Digest::MD5.new
|
19
28
|
@attributes.each do |k,v|
|
@@ -22,11 +31,17 @@ module JSON2Ruby
|
|
22
31
|
md5.hexdigest
|
23
32
|
end
|
24
33
|
|
34
|
+
# Compare this Entity with another. An entity is equal to another entity if and only if it has:
|
35
|
+
# * The same number of fields
|
36
|
+
# * The fields have the same case-sensitive name
|
37
|
+
# * The fields have the same types, as tested with `attr_hash`
|
38
|
+
# i.e. in short, an entity is equal to another entity if and only if both +attr_hash+ calls return the same value.
|
25
39
|
def ==(other)
|
26
40
|
return false if other.class != self.class
|
27
41
|
attr_hash == other.attr_hash
|
28
42
|
end
|
29
43
|
|
44
|
+
# Reset the internal type cache for all Entities everywhere, and reset the global Unknown number.
|
30
45
|
def self.reset_parse
|
31
46
|
@@objs = {
|
32
47
|
RUBYSTRING.attr_hash => RUBYSTRING,
|
@@ -38,6 +53,11 @@ module JSON2Ruby
|
|
38
53
|
@@unknowncount = 0
|
39
54
|
end
|
40
55
|
|
56
|
+
# Create a new, or return an existing, Entity named name that supports all fields in obj_hash.
|
57
|
+
# Optionally, options can be supplied:
|
58
|
+
# * :forcenumeric => true - Use RUBYNUMERIC instead of RUBYINTEGER / RUBYFLOAT.
|
59
|
+
#
|
60
|
+
# Note: Contained JSON Objects and Arrays will be recursively parsed into Entity and Collection instances.
|
41
61
|
def self.parse_from(name, obj_hash, options = {})
|
42
62
|
ob = self.new(name)
|
43
63
|
obj_hash.each do |k,v|
|
@@ -70,16 +90,20 @@ module JSON2Ruby
|
|
70
90
|
ob
|
71
91
|
end
|
72
92
|
|
93
|
+
# Return the type cache of all Entity objects.
|
94
|
+
# This is a Hash of +hash_attr+ values to +Entity+ instances.
|
73
95
|
def self.entities
|
74
96
|
@@objs
|
75
97
|
end
|
76
98
|
|
99
|
+
# Return a string of the form 'Unknown<x>' where <x> is a globally unique sequence.
|
77
100
|
def self.get_next_unknown
|
78
101
|
@@unknowncount ||= 0
|
79
102
|
@@unknowncount += 1
|
80
103
|
"Unknown#{@@unknowncount}"
|
81
104
|
end
|
82
105
|
|
106
|
+
# Return a string of the form ' (<y>)' where <y> is the original_name of the Entity
|
83
107
|
def comment
|
84
108
|
x = @name
|
85
109
|
x += " (#{@original_name})" unless @original_name.nil?
|
data/lib/json2ruby/primitive.rb
CHANGED
@@ -1,21 +1,30 @@
|
|
1
1
|
module JSON2Ruby
|
2
|
-
|
2
|
+
# Represents a JSON Primitive. You should not instantiate this class - use the static instances:
|
3
|
+
# * JSON2Ruby::RUBYSTRING for JSON Strings
|
4
|
+
# * JSON2Ruby::RUBYINTEGER for JSON Integers
|
5
|
+
# * JSON2Ruby::RUBYFLOAT for JSON Floats
|
6
|
+
# * JSON2Ruby::RUBYBOOLEAN for JSON Booleans
|
7
|
+
# * JSON2Ruby::RUBYNUMERIC for JSON Numerics (Integers or floats)
|
3
8
|
class Primitive
|
4
|
-
|
9
|
+
# The +String+ name of the Primitive.
|
10
|
+
attr_accessor :name
|
11
|
+
# +String+ Exists for compatibility.
|
12
|
+
attr_accessor :original_name
|
13
|
+
# The static +attr_hash+ of the Primitive.
|
14
|
+
attr_accessor :attr_hash
|
5
15
|
|
16
|
+
# The short name is 'Primitive'
|
6
17
|
def self.short_name
|
7
18
|
"Primitive"
|
8
19
|
end
|
9
20
|
|
21
|
+
# Create a new Primitive with the specified +name+ and +attr_hash+
|
10
22
|
def initialize(name, attr_hash)
|
11
23
|
@name = name
|
12
24
|
@attr_hash = attr_hash
|
13
25
|
end
|
14
26
|
|
15
|
-
|
16
|
-
@attr_hash
|
17
|
-
end
|
18
|
-
|
27
|
+
# Return the +name+ of the Primitive
|
19
28
|
def comment
|
20
29
|
@name
|
21
30
|
end
|
@@ -30,5 +39,5 @@ module JSON2Ruby
|
|
30
39
|
# Primitive Representing a Ruby Boolean
|
31
40
|
RUBYBOOLEAN = Primitive.new("Boolean","0123456789ABCDEF0123456789ABCDE2")
|
32
41
|
# Psuedo-Primitive Representing a Numeric
|
33
|
-
RUBYNUMERIC = Primitive.new("Numeric","
|
42
|
+
RUBYNUMERIC = Primitive.new("Numeric","0123456789ABCDEF0123456789ABCDE3")
|
34
43
|
end
|
@@ -3,7 +3,16 @@ require 'json'
|
|
3
3
|
require 'optparse'
|
4
4
|
|
5
5
|
module JSON2Ruby
|
6
|
+
# The RubyWriter class contains methods to output ruby code from a given Entity.
|
6
7
|
class RubyWriter
|
8
|
+
# Return a String containing a Ruby class/module definition for the given Entity.
|
9
|
+
# Optionally, supply indent to set the indent of the generated code in spaces,
|
10
|
+
# and supply a Hash of options as follows:
|
11
|
+
# * :modules - Boolean if true, generate Ruby +module+ files instead of classes.
|
12
|
+
# * :require - Array of String items, each of which will generate a `require '<x>'` statement for each item
|
13
|
+
# * :superclass_name - String, if supplied, the superclass of the class to geneerate
|
14
|
+
# * :extend - Array of String items, each of which will generate a `extend '<x>'` statement for each item in the class
|
15
|
+
# * :include - Array of String items, each of which will generate a `include '<x>'` statement for each item in the class
|
7
16
|
def self.to_code(entity, indent = 0, options = {})
|
8
17
|
x = ""
|
9
18
|
if options.has_key?(:require)
|
@@ -27,7 +36,14 @@ module JSON2Ruby
|
|
27
36
|
x
|
28
37
|
end
|
29
38
|
|
30
|
-
|
39
|
+
# Return a String containing the Ruby code for each Attribute definition for in the supplied Entity.
|
40
|
+
# Optionally, supply indent to set the indent of the generated code in spaces,
|
41
|
+
# and supply a Hash of options as follows:
|
42
|
+
# * :attributemethod - String, the method to call to define attributes
|
43
|
+
# * :collectionmethod - String, the method to call to define collections
|
44
|
+
# * :includetypes - Boolean if true, include the string of the Attribute type as a second parameter to the definition call.
|
45
|
+
# * :namespace - String, the namespace of the type classes in the format 'Module::SubModule'...
|
46
|
+
def self.attributes_to_ruby(entity, indent = 0, options = {})
|
31
47
|
ident = (' '*indent)
|
32
48
|
x = ""
|
33
49
|
entity.attributes.each do |k,v|
|
data/lib/json2ruby/version.rb
CHANGED
data/spec/collection_spec.rb
CHANGED
@@ -62,8 +62,8 @@ describe JSON2Ruby::Collection do
|
|
62
62
|
|
63
63
|
expect(col).to be_a(JSON2Ruby::Collection)
|
64
64
|
expect(col.name).to eq("Test")
|
65
|
-
expect(col.ruby_types.length).to eq(
|
66
|
-
expect(col.attr_hash).to eq("
|
65
|
+
expect(col.ruby_types.length).to eq(5)
|
66
|
+
expect(col.attr_hash).to eq("94db8ab7a9379e835f6a69714fbec9cc")
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
data/spec/entity_spec.rb
CHANGED
@@ -59,7 +59,7 @@ describe JSON2Ruby::Entity do
|
|
59
59
|
expect(ent).to be_a(JSON2Ruby::Entity)
|
60
60
|
expect(ent.name).to eq("Test")
|
61
61
|
expect(ent.attributes.length).to eq(6)
|
62
|
-
expect(ent.attr_hash).to eq("
|
62
|
+
expect(ent.attr_hash).to eq("5681e2da2b9aa0a343e622ef771c0abb")
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
data/spec/primitive_spec.rb
CHANGED
@@ -45,7 +45,7 @@ describe JSON2Ruby::Primitive do
|
|
45
45
|
expect(JSON2Ruby::RUBYBOOLEAN.attr_hash).to eq('0123456789ABCDEF0123456789ABCDE2')
|
46
46
|
|
47
47
|
expect(JSON2Ruby::RUBYNUMERIC.name).to eq('Numeric')
|
48
|
-
expect(JSON2Ruby::RUBYNUMERIC.attr_hash).to eq('
|
48
|
+
expect(JSON2Ruby::RUBYNUMERIC.attr_hash).to eq('0123456789ABCDEF0123456789ABCDE3')
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json2ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-08-
|
12
|
+
date: 2015-08-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: coveralls
|
@@ -223,3 +223,4 @@ test_files:
|
|
223
223
|
- spec/primitive_spec.rb
|
224
224
|
- spec/ruby_writer_spec.rb
|
225
225
|
- spec/spec_helper.rb
|
226
|
+
has_rdoc:
|