json2ruby 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://travis-ci.org/tomdionysus/json2ruby.svg?branch=master)](https://travis-ci.org/tomdionysus/json2ruby) [![Coverage Status](https://coveralls.io/repos/tomdionysus/json2ruby/badge.svg?branch=master&service=github)](https://coveralls.io/github/tomdionysus/json2ruby?branch=master)
|
3
|
+
[![Build Status](https://travis-ci.org/tomdionysus/json2ruby.svg?branch=master)](https://travis-ci.org/tomdionysus/json2ruby) [![Coverage Status](https://coveralls.io/repos/tomdionysus/json2ruby/badge.svg?branch=master&service=github)](https://coveralls.io/github/tomdionysus/json2ruby?branch=master) [![Gem Version](https://badge.fury.io/rb/json2ruby.svg)](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:
|