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 CHANGED
@@ -1,4 +1,5 @@
1
1
  coverage
2
2
  testjson
3
3
  classes
4
+ doc
4
5
  *.gem
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json2ruby (0.1.0)
4
+ json2ruby (0.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
- git clone git@github.com:tomdionysus/json2ruby.git
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
@@ -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
- attr_accessor :name, :original_name, :ruby_type
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
@@ -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)
@@ -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
- attr_accessor :name, :original_name, :ruby_types
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?
@@ -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
- attr_accessor :name, :original_name, :attributes
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?
@@ -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
- attr_accessor :name, :original_name, :attr_hash
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
- def attr_hash
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","0123456789ABCDEF0123456789ABCDE2")
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
- def self.attributes_to_ruby(entity, indent, options = {})
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|
@@ -1,3 +1,5 @@
1
+ # The JSON2Ruby module encapsulates all classes and constants for the json2ruby gem and executable.
1
2
  module JSON2Ruby
2
- VERSION = '0.1.0'
3
+ # The Version of this json2ruby
4
+ VERSION = '0.1.1'
3
5
  end
@@ -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(4)
66
- expect(col.attr_hash).to eq("e38d96234bfbf21545ed4ab2128b9ab4")
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
 
@@ -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("592884f7d98c4a31b7d641b10636d546")
62
+ expect(ent.attr_hash).to eq("5681e2da2b9aa0a343e622ef771c0abb")
63
63
  end
64
64
  end
65
65
 
@@ -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('0123456789ABCDEF0123456789ABCDE2')
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.0
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-21 00:00:00.000000000 Z
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: