json-schema-generator 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
- [submodule "tests"]
2
- path = tests
3
- url = git://github.com/maxlinc/json-schema-kata.git
1
+ [submodule "kata"]
2
+ path = kata
3
+ url = https://github.com/maxlinc/json-schema-kata.git
@@ -4,9 +4,5 @@ rvm:
4
4
  - 1.9.3
5
5
  - jruby-19mode
6
6
  - rbx-19mode
7
- env:
8
- EXCLUDE_SCHEMA_VERSION=draft4
9
- JSON_GENERATOR="bundle exec json_schema_generator"
10
7
  before_install:
11
8
  - git submodule update --init --recursive
12
- - cd tests && bundle install
data/README.md CHANGED
@@ -1,43 +1,14 @@
1
1
  # JSON::SchemaGenerator
2
2
 
3
- A very basic json-schema generator. Currently only has draft-03 support.
4
- The tests, including draft-04 tests, are in the json-schema-kata submodule.
3
+ JSON::SchemaGenerator tries to save you some time writing [json-schemas](http://json-schema.org/) based on existing data. I know that there are multiple valid json-schemas that could be generated for any given sample, so I won't generate the exact schema you want. Our goal is just to make reasonable assumptions that get you close, so you can generate the basic structure and then customize your schema, rather than writing hundreds of lines by hand.
5
4
 
6
- ## Installation
7
-
8
- Add this line to your application's Gemfile:
5
+ There are [many json-schema validators], but only a few generators. The best generator I've found is a closed-source web app so you can't embed it. I couldn't find anything to embed within an open-source Ruby project ([Pacto](https://github.com/thoughtworks/pacto)), so I hacked one together quickly.
9
6
 
10
- gem 'json-schema-generator'
7
+ My quick, yak-shaving implementaiton wasn't designed for maintainability, but I wrote a test suite that gives me the confidence to rewrite or even port to other languages. The tests are in [json-schema-kata](https://github.com/maxlinc/json-schema-kata). I called it a kata for a reason:
11
8
 
12
- And then execute:
13
-
14
- $ bundle
15
-
16
- Or install it yourself as:
17
-
18
- $ gem install json-schema-generator
19
-
20
- ## Usage
21
-
22
- JSON::SchemaGenerator.generate name, data, version
23
-
24
- e.g.
25
-
26
- JSON::SchemaGenerator.generate 'sample_file.json', File.read('sample_file.json'), 'draft3'
27
-
28
- ## Testing
29
-
30
- The tests are actually in a reusable submodule of platform agnostic json-schema tests.
31
-
32
- ## Contributing
33
-
34
- 1. Fork it
35
- 2. Create your feature branch (`git checkout -b my-new-feature`)
36
- 3. Commit your changes (`git commit -am 'Add some feature'`)
37
- 4. Push to the branch (`git push origin my-new-feature`)
38
- 5. Create new Pull Request
39
-
40
- TODO: Write a gem description
9
+ > Code Kata is an attempt to bring this element of practice to software development. A kata is an exercise in karate where you repeat a form many, many times, making little improvements in each. The intent behind code kata is similar.
10
+ >
11
+ > Dave Thomas [Code Kata](http://codekata.pragprog.com/2007/01/code_kata_backg.html)
41
12
 
42
13
  ## Installation
43
14
 
@@ -55,46 +26,50 @@ Or install it yourself as:
55
26
 
56
27
  ## Usage
57
28
 
58
- TODO: Write usage instructions here
59
-
60
- ## Contributing
61
-
62
- 1. Fork it
63
- 2. Create your feature branch (`git checkout -b my-new-feature`)
64
- 3. Commit your changes (`git commit -am 'Add some feature'`)
65
- 4. Push to the branch (`git push origin my-new-feature`)
66
- 5. Create new Pull Request
29
+ Command line:
30
+ ```sh
31
+ # Usage: json-schema-generator --help
32
+ # Simple example:
33
+ $ json-schema-generator my_sample.json --schema-version draft3
34
+ ```
67
35
 
68
- TODO: Write a gem description
36
+ Ruby:
37
+ ```ruby
38
+ file = 'my_sample.json' # or any identifier for the description
39
+ JSON::SchemaGenerator.generate file, File.read(file), {:schema_version => 'draft3'}
40
+ ```
69
41
 
70
- ## Installation
42
+ ## Features
71
43
 
72
- Add this line to your application's Gemfile:
44
+ JSON::SchemaGenerate has the following features or assumptions for generating "best-guess" schemas:
73
45
 
74
- gem 'json-schema-generator'
46
+ * **Schema Versions**: Support draft3 and draft4 of json-schema.
47
+ * **Options**:
48
+ * **Defaults**: Can generate default values.
49
+ * **Descriptions**: Can generate a description indicating where the schema came from.
50
+ * **Features/Assumptions**:
51
+ * **Detecting optional properties:** if you have an array of hashes, then will detect which hash keys exist in every instance of the hash and which ones only exist in some, and use this data to decide if the key is required or optional in the schema.
52
+ * **Assume required:** in all other cases, I assume everything I find in the sample is required. I believe it is better to generate a schema that is too strict than too lenient. It is easy to review and fix false negatives, by updating the schema to mark those items as optional. A false positive will go unnoticed and will not point you towards a solution.
53
+ * **Detect types:** I detect objects, arrays, strings, integers, numbers and booleans.
75
54
 
76
- And then execute:
55
+ ## Known issues
77
56
 
78
- $ bundle
57
+ * Currently assumes the root element is a hash. Generation will fail for data that has an array as the root.
79
58
 
80
- Or install it yourself as:
59
+ ## Tests
81
60
 
82
- $ gem install json-schema-generator
61
+ This was a [yak shaving](http://en.wiktionary.org/wiki/yak_shaving) project. I needed to generate schemas for a ruby project. I wanted to embed a schema generator within a larger open-source project ([Pacto](https://github.com/thoughtworks/pacto)), and couldn't find one I could use. So I wrote one.
83
62
 
84
- ## Usage
63
+ There are [many json-schema validators], but only a few generators. The best generator I've found is a closed-source Web app so you can't embed it. I'm hoping more people will write generators in more languages. I also hope someone replaces my quick "yak-shaving" implementation
64
+ There are many json-schema validators available in many different programming languages. However, there are only a few generators. I hacked this together quickly because I wanted one I could easily use in Ruby. My implementaiton is yak-shaving, not a well-design and maintainable solution. So I wanted acceptance tests that are fully decoupled from the implementation - even the programming language - so I can completely re-write my solution or port it to other languages.
85
65
 
86
- TODO: Write usage instructions here
66
+ The tests are in the json-schema-kata project. The test runner is ruby, but it makes no assumptions about the implementation language. Feel free to use my tests to port to any language.
87
67
 
88
68
  ## Contributing
89
69
 
90
- 1. Fork it
91
- 2. Create your feature branch (`git checkout -b my-new-feature`)
92
- 3. Commit your changes (`git commit -am 'Add some feature'`)
93
- 4. Push to the branch (`git push origin my-new-feature`)
94
- 5. Create new Pull Request
95
- TODO: Write usage instructions here
70
+ Contributions Welcome! It's easy to contribute tests to the json-schema-kata project. You just need to add a sample and what you think the generated schema should look like for each supported json-schema version (draft3, draft4, etc).
96
71
 
97
- ## Contributing
72
+ Rewrites, ports, tutorials: I called the tests a "kata" because it is a small problem that is good for practicing programming skills, but could be solved many different ways. Can you implement a generator using functional programming? An internal DSL? JSONPath? Seven languages in seven Weeks? Try it out, hone your skills, and share your results.
98
73
 
99
74
  1. Fork it
100
75
  2. Create your feature branch (`git checkout -b my-new-feature`)
data/Rakefile CHANGED
@@ -3,9 +3,13 @@ require "bundler/gem_tasks"
3
3
  task :default => :test
4
4
 
5
5
  task :test do
6
- ENV['JSON_GENERATOR'] = 'bundle exec json_schema_generator'
7
6
  ENV['PATH'] = ENV['PATH'] + File::PATH_SEPARATOR + File.expand_path('bin', Dir.pwd)
8
7
  puts ENV['PATH']
9
- system 'cd tests && bundle exec rake'
8
+ Bundler.with_clean_env do
9
+ Dir.chdir 'kata' do
10
+ system 'bundle install'
11
+ system 'bundle exec rake'
12
+ end
13
+ end
10
14
  fail 'Tests did not pass!' unless $?.success?
11
15
  end
@@ -4,19 +4,31 @@ module JSON
4
4
  class SchemaGenerator
5
5
  DRAFT3 = 'draft-03'
6
6
  DRAFT4 = 'draft-04'
7
+ DEFAULT_VERSION = 'draft3'
8
+ SUPPORTED_VERSIONS = ['draft3', 'draft4']
7
9
 
8
10
  class << self
9
- def generate name, data, version
10
- generator = JSON::SchemaGenerator.new name, version
11
+ def generate name, data, opts = {}
12
+ generator = JSON::SchemaGenerator.new name, opts
11
13
  generator.generate data
12
14
  end
13
15
  end
14
16
 
15
- def initialize name, version = 'draft3'
17
+ def initialize name, opts = {}
18
+ version = opts[:schema_version] || DEFAULT_VERSION
19
+ # Unfortunately json-schema.org and json-schema (gem) use different version strings
20
+ if ['draft3', 'draft-03'].include? version.to_s.downcase
21
+ @version = DRAFT3
22
+ elsif ['draft4', 'draft-04'].include? version.to_s.downcase
23
+ @version = DRAFT4
24
+ else
25
+ abort "Unsupported schema version: #{version}"
26
+ end
27
+
28
+ @defaults = opts[:defaults]
29
+
16
30
  @buffer = StringIO.new
17
31
  @name = name
18
- @version = DRAFT3 if version == 'draft3'
19
- @version = DRAFT4 if version == 'draft4'
20
32
  end
21
33
 
22
34
  def generate raw_data
@@ -53,12 +65,11 @@ module JSON
53
65
 
54
66
  statement_group.add "\"type\": \"#{type}\""
55
67
  statement_group.add "\"required\": #{required}" if @version == DRAFT3
56
- # statement_group.add "\"default\": #{value.inspect}"
68
+ statement_group.add "\"default\": #{value.inspect}" if @defaults
57
69
  end
58
70
 
59
71
  def create_values(key, value, required_keys = nil, in_array = false)
60
72
  statement_group = StatementGroup.new key
61
- # buffer.puts "\"#{key}\": {"
62
73
  case value
63
74
  when NilClass
64
75
  when TrueClass, FalseClass, String, Integer, Float
@@ -78,13 +89,12 @@ module JSON
78
89
  end
79
90
 
80
91
  def create_hash(statement_group, data, required_keys)
81
- # statement_group = StatementGroup.new
82
92
  statement_group.add '"type": "object"'
83
93
  statement_group.add '"required": true' if @version == DRAFT3
84
94
  if @version == DRAFT4
85
95
  required_keys ||= []
86
96
  required_string = required_keys.map(&:inspect).join ', '
87
- statement_group.add "\"required\": [#{required_string}]"
97
+ statement_group.add "\"required\": [#{required_string}]" unless required_keys.empty?
88
98
  end
89
99
  statement_group.add create_hash_properties data, required_keys
90
100
  statement_group
@@ -99,7 +109,6 @@ module JSON
99
109
  end
100
110
 
101
111
  def create_array(statement_group, data, required_keys)
102
- # statement_group = StatementGroup.new
103
112
  statement_group.add '"type": "array"'
104
113
  statement_group.add '"required": true' if @version == DRAFT3
105
114
  if data.size == 0
@@ -1,5 +1,5 @@
1
1
  module JSON
2
2
  class SchemaGenerator
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
@@ -1,12 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+
1
5
  class JSON::SchemaGeneratorCLI
2
6
  def initialize(argv, stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel)
3
7
  @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
4
8
  end
5
9
 
6
10
  def execute!
11
+ default_version = JSON::SchemaGenerator::DEFAULT_VERSION
12
+ supported_versions = JSON::SchemaGenerator::SUPPORTED_VERSIONS
13
+
14
+ options = {
15
+ :schema_version => default_version,
16
+ :defaults => false
17
+ }
18
+
19
+
20
+
21
+ OptionParser.new do |opts|
22
+ opts.on("--defaults", "Record default values in the generated schema") { options[:defaults] = true }
23
+ opts.on("--schema-version [VERSION]", [:draft3, :draft4],
24
+ "Version of json-schema to generate (#{supported_versions.join ', '}). Default: #{default_version}") do |schema_version|
25
+ options[:schema_version] = schema_version
26
+ end
27
+ opts.parse!
28
+ end
29
+
7
30
  file = ARGV.shift
8
- version = ARGV.shift || 'draft3'
9
- schema = JSON.parse(JSON::SchemaGenerator.generate file, File.read(file), version)
31
+ schema = JSON.parse(JSON::SchemaGenerator.generate file, File.read(file), options)
10
32
  @stdout.puts JSON.pretty_generate schema
11
33
  @kernel.exit(0)
12
34
  end
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ file=$1
3
+ bundle exec json-schema-generator $1 --schema-version draft4 --defaults
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ file=$1
3
+ bundle exec json-schema-generator $1
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ file=$1
3
+ bundle exec json-schema-generator $1 --schema-version draft4
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-schema-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
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: 2013-11-06 00:00:00.000000000 Z
12
+ date: 2013-11-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -111,7 +111,7 @@ description: A very basic json-schema generator
111
111
  email:
112
112
  - max@devopsy.com
113
113
  executables:
114
- - json_schema_generator
114
+ - json-schema-generator
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
@@ -122,13 +122,16 @@ files:
122
122
  - LICENSE.txt
123
123
  - README.md
124
124
  - Rakefile
125
- - bin/json_schema_generator
125
+ - bin/json-schema-generator
126
126
  - json-schema-generator.gemspec
127
127
  - lib/json-schema-generator.rb
128
128
  - lib/json/schema_generator.rb
129
129
  - lib/json/schema_generator/statement_group.rb
130
130
  - lib/json/schema_generator/version.rb
131
131
  - lib/json/schema_generator_cli.rb
132
+ - scripts/challenges/generate_defaults
133
+ - scripts/challenges/generate_draft3
134
+ - scripts/challenges/generate_draft4
132
135
  homepage: ''
133
136
  licenses:
134
137
  - MIT
@@ -142,12 +145,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
145
  - - ! '>='
143
146
  - !ruby/object:Gem::Version
144
147
  version: '0'
148
+ segments:
149
+ - 0
150
+ hash: -2342599026484996065
145
151
  required_rubygems_version: !ruby/object:Gem::Requirement
146
152
  none: false
147
153
  requirements:
148
154
  - - ! '>='
149
155
  - !ruby/object:Gem::Version
150
156
  version: '0'
157
+ segments:
158
+ - 0
159
+ hash: -2342599026484996065
151
160
  requirements: []
152
161
  rubyforge_project:
153
162
  rubygems_version: 1.8.23
@@ -155,4 +164,3 @@ signing_key:
155
164
  specification_version: 3
156
165
  summary: A very basic json-schema generator
157
166
  test_files: []
158
- has_rdoc: