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.
- data/.gitmodules +3 -3
- data/.travis.yml +0 -4
- data/README.md +36 -61
- data/Rakefile +6 -2
- data/bin/{json_schema_generator → json-schema-generator} +0 -0
- data/lib/json/schema_generator.rb +19 -10
- data/lib/json/schema_generator/version.rb +1 -1
- data/lib/json/schema_generator_cli.rb +24 -2
- data/scripts/challenges/generate_defaults +3 -0
- data/scripts/challenges/generate_draft3 +3 -0
- data/scripts/challenges/generate_draft4 +3 -0
- metadata +13 -5
data/.gitmodules
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
[submodule "
|
2
|
-
path =
|
3
|
-
url =
|
1
|
+
[submodule "kata"]
|
2
|
+
path = kata
|
3
|
+
url = https://github.com/maxlinc/json-schema-kata.git
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,43 +1,14 @@
|
|
1
1
|
# JSON::SchemaGenerator
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
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
|
-
##
|
42
|
+
## Features
|
71
43
|
|
72
|
-
|
44
|
+
JSON::SchemaGenerate has the following features or assumptions for generating "best-guess" schemas:
|
73
45
|
|
74
|
-
|
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
|
-
|
55
|
+
## Known issues
|
77
56
|
|
78
|
-
|
57
|
+
* Currently assumes the root element is a hash. Generation will fail for data that has an array as the root.
|
79
58
|
|
80
|
-
|
59
|
+
## Tests
|
81
60
|
|
82
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
File without changes
|
@@ -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,
|
10
|
-
generator = JSON::SchemaGenerator.new name,
|
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,
|
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
|
-
|
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,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
|
-
|
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
|
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.
|
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-
|
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
|
-
-
|
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/
|
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:
|