jsoncop 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe2dadd4db52fbf4f373d7219133ee6a400c3c61
4
- data.tar.gz: e7ce11ffaa6a534e095b73d5301e6f04a622181d
3
+ metadata.gz: 6d68292e78bb6f41e6f716a177702537eb7af012
4
+ data.tar.gz: 7d9f747880b9f1016543e68427a65efe25530066
5
5
  SHA512:
6
- metadata.gz: ae267be67d57306b869c5e5bc267691941d3a4ea25dfff9188d322646da8e6d1187cb8d8268a841442c5fe5d965e55cc407e23470219e15c8bac12528eebc290
7
- data.tar.gz: d1bbf93c5b176cf40c734113727e09068c0b2e2ee0d16b582a59858add6554023af9941350c096c140d2579ba63914092b575a7a493455d66aef0be66969caf9
6
+ metadata.gz: 455670249f7eb076763eb09268602d7658ab4446bd6e70a4c164aa8e4b29c00c9b65a8d4910883bd0cc4f7c39b14a0b76b6b32845cb59374a76e52cfc5167024
7
+ data.tar.gz: 05b4142380220cdd1cc5e645225ab6482901508b2b1b0bf4258dbc996f0fd1b6fa1e7d184f0e776a3fe87ddb48aa7b75786bc0adcb13ea02fd407bd0c7bb42a6
data/README.md CHANGED
@@ -19,44 +19,26 @@ let person = Person.parse(json: json)
19
19
 
20
20
  ## Usage
21
21
 
22
- Define a model with and implement `static func JSONKeyPathByPropertyKey` method:
22
+ Define a model with and **add `//@jsoncop` just before model definition line**:
23
23
 
24
24
  ```swift
25
- // jsoncop: enabled
26
-
25
+ //@jsoncop
27
26
  struct Person {
28
27
  let id: Int
29
28
  let name: String
30
- let createdAt: Date
31
-
32
- static func JSONKeyPathByPropertyKey() -> [String: String] {
33
- return [
34
- "id": "id",
35
- "name": "name",
36
- "createdAt": "createdAt"
37
- ]
38
- }
39
-
40
- static func createdAtJSONTransformer(value: Any) -> Date? {
41
- guard let value = value as? Double else { return nil }
42
- return Date(timeIntervalSinceNow: value)
43
- }
44
29
  }
45
30
  ```
46
-
47
- > DO NOT forget to add "// jsoncop: enabled" before struct.
48
-
49
31
  Run `cop install` in project root folder.
50
32
 
51
33
  ```shell
52
34
  $ cop install
53
35
  ```
54
36
 
55
- This will generate several parsing methods in current file:
37
+ This will generate several parsing methods in current file without affecting other part of your codes:
56
38
 
57
39
  ![](./images/jsoncop-demo.png)
58
40
 
59
- All the code between `generate-start` and `generate-end` and will be replaced when re-run `cop install` in current project folder. Other codes will remain unchanged. Please don't write any codes in this area.
41
+ All the code between `// MARK: - JSONCop-Start` and `// MARK: - JSONCop-End` and will be replaced when re-run `cop install` in current project folder. Other codes will remain unchanged. Please don't write any codes in this area.
60
42
 
61
43
  ## Installation
62
44
 
@@ -3,16 +3,18 @@ module JSONCop
3
3
 
4
4
  require 'jsoncop/model/model'
5
5
  require 'jsoncop/model/attribute'
6
+ require 'jsoncop/model/transformer'
6
7
 
7
- JSON_COP_ENABLED = /jsoncop: enabled/
8
+ JSON_COP_ENABLED = /@jsoncop/
8
9
 
10
+ NEED_PARSING_CONTENT = /(\/\/\s*@jsoncop\s+(?:struct|class)(?:.|\s)*?\n})/
9
11
  MODEL_NAME_REGEX = /(struct|class)\s+(.+)\s*{/
10
12
  ATTRIBUTE_REGEX = /^\s+(let|var)\s(.+):(.+)/
11
- JSON_TRANSFORMER_REGEX = /^\s+static\s+func\s+(.+)JSONTransformer.+->.+/
13
+ JSON_TRANSFORMER_REGEX = /^\s+static\s+func\s+(.+)JSONTransformer\(.+?\:(.+)\).+->.+/
12
14
  JSON_BY_PROPERTY_HASH_REGEX = /static\s+func\s+JSONKeyPathByPropertyKey\(\)\s*->\s*\[String\s*:\s*String\]\s*{\s*return\s*(\[[\s"a-z0-9A-Z_\-:\[\],]*)}/
13
15
 
14
16
  attr_reader :file_path
15
- attr_accessor :model
17
+ attr_accessor :current_model
16
18
 
17
19
  def initialize(file_path)
18
20
  @file_path = file_path
@@ -21,23 +23,33 @@ module JSONCop
21
23
  def analyze!
22
24
  content = File.read file_path
23
25
  return unless content =~ JSON_COP_ENABLED
24
- content.each_line do |line|
25
- if line =~ MODEL_NAME_REGEX
26
- model_name = line.scan(MODEL_NAME_REGEX).flatten.last
27
- @model = Model::Model.new model_name
28
- elsif line =~ ATTRIBUTE_REGEX
29
- result = line.scan(ATTRIBUTE_REGEX).flatten
30
- @model.attributes << Model::Attribute.new(result[1], result[2])
31
- elsif line =~ JSON_TRANSFORMER_REGEX
32
- result = line.scan(JSON_TRANSFORMER_REGEX).flatten
33
- @model.transformers << result.first
26
+ models = []
27
+ content.scan(NEED_PARSING_CONTENT).flatten.each do |content|
28
+ content.each_line do |line|
29
+ if line =~ MODEL_NAME_REGEX
30
+ model_name = line.scan(MODEL_NAME_REGEX).flatten.last
31
+ @current_model = Model::Model.new model_name
32
+ models << @current_model
33
+ elsif line =~ ATTRIBUTE_REGEX
34
+ result = line.scan(ATTRIBUTE_REGEX).flatten
35
+ @current_model.attributes << Model::Attribute.new(result[1], result[2])
36
+ elsif line =~ JSON_TRANSFORMER_REGEX
37
+ result = line.scan(JSON_TRANSFORMER_REGEX).flatten
38
+ @current_model.transformers << Model::Transformer.new(result[0], result[1])
39
+ end
34
40
  end
41
+
42
+ json_attr_list = content.scan(JSON_BY_PROPERTY_HASH_REGEX).flatten.first
43
+ if json_attr_list
44
+ json_attr_list.gsub!(/[(\[\]"\s)]*/, '')
45
+ @current_model.attr_json_hash = Hash[json_attr_list.split(",").map {
46
+ |attr_json_pair| attr_json_pair.split(":").reverse
47
+ }]
48
+ end
49
+
35
50
  end
36
51
 
37
- json_attr_list = content.scan(JSON_BY_PROPERTY_HASH_REGEX).flatten.first
38
- json_attr_list.gsub!(/[(\[\]"\s)]*/, '')
39
- @model.attr_json_hash = Hash[json_attr_list.split(",").map { |attr_json_pair| attr_json_pair.split(":").reverse }]
40
- @model
52
+ models
41
53
  end
42
54
 
43
55
  end
@@ -7,47 +7,75 @@ module JSONCop
7
7
  attr_reader :file_path
8
8
  attr_reader :model
9
9
 
10
- def initialize(file_path, model)
10
+ def initialize(file_path, models)
11
11
  @file_path = file_path
12
- @model = model
12
+ @models = models
13
13
  end
14
14
 
15
15
  def generate!
16
- jsoncop_generate_start = /jsoncop: generate\-start/
17
- jsoncop_generate_end = /jsoncop: generate\-end/
16
+ jsoncop_generate_start = /\/\/ MARK: \- JSONCop\-Start/
17
+ jsoncop_generate_end = /\/\/ MARK: \- JSONCop\-End/
18
18
  content = File.read file_path
19
19
  if content.match(jsoncop_generate_start) && content.match(jsoncop_generate_end)
20
- content.gsub!(/\/\/ jsoncop: generate-start[^$]*jsoncop: generate\-end/, "")
20
+ content.gsub!(/\/\/ MARK: \- JSONCop\-Start[^$]*MARK: \- JSONCop\-End/, json_cop_template)
21
+ else
22
+ content += json_cop_template
21
23
  end
22
- File.write file_path, content + json_cop_template
24
+ File.write file_path, content
23
25
  end
24
26
 
25
27
  def json_cop_template
26
- <<-JSONCOP
27
- // jsoncop: generate-start
28
-
29
- extension #{@model.name} {
30
- static func parse(json: [String: Any]) -> #{@model.name}? {
31
- guard #{json_parsing_template} else { return nil }
32
- return #{@model.name}(#{model.key_value_pair})
28
+ result = "// MARK: - JSONCop-Start\n\n"
29
+ @models.each do |model|
30
+ result += <<-JSONCOP
31
+ extension #{model.name} {
32
+ static func parse(json: Any) -> #{model.name}? {
33
+ guard let json = json as? [String: Any] else { return nil }
34
+ guard #{json_parsing_template model} else { return nil }
35
+ return #{model.name}(#{model.key_value_pair})
33
36
  }
34
- static func parse(jsons: [[String: Any]]) -> [#{@model.name}] {
37
+ static func parses(jsons: Any) -> [#{model.name}] {
38
+ guard let jsons = jsons as? [[String: Any]] else { return [] }
35
39
  return jsons.flatMap(parse)
36
40
  }
37
41
  }
38
42
 
39
- // jsoncop: generate-end
40
- JSONCOP
43
+ JSONCOP
44
+ # result += <<-CODING
45
+ # extension #{model.name}: NSCoding {
46
+ # func encode(with aCoder: NSCoder) {
47
+ #
48
+ # }
49
+ #
50
+ # init?(coder decoder: NSCoder) {
51
+ # guard #{decode_template model} else { return nil }
52
+ #
53
+ # self.init(#{model.key_value_pair})
54
+ # }
55
+ # }
56
+ #
57
+ # CODING
58
+ end
59
+ result += "// MARK: - JSONCop-End"
60
+ result
41
61
  end
42
62
 
43
- def json_parsing_template
44
- @model.attributes.map do |attr|
45
- if @model.transformers.include? attr.name
46
- "let #{attr.name} = (json[\"#{@model.attr_json_hash[attr.name]}\"]).flatMap(#{attr.name}JSONTransformer)"
63
+ def json_parsing_template(model)
64
+ model.attributes.map do |attr|
65
+ transformer = model.transformers.select { |t| t.name == attr.name }.first
66
+ if transformer
67
+ "let #{attr.name} = (json[\"#{model.attr_json_hash[attr.name] || attr.name}\"] as? #{transformer.type}).flatMap(#{attr.name}JSONTransformer)"
47
68
  else
48
- "let #{attr.name} = json[\"#{@model.attr_json_hash[attr.name]}\"] as? #{attr.type}"
69
+ "let #{attr.name} = json[\"#{model.attr_json_hash[attr.name] || attr.name}\"] as? #{attr.type}"
49
70
  end
50
- end.join(",\n\t\t")
71
+ end.join(",\n\t\t\t")
51
72
  end
73
+
74
+ def decode_template(model)
75
+ model.attributes.map do |attr|
76
+ "let #{attr.name} = decoder.decode#{attr.decode_type}(forKey: \"#{attr.name}\") as? #{attr.type}"
77
+ end.join(",\n\t\t\t")
78
+ end
79
+
52
80
  end
53
81
  end
@@ -6,6 +6,27 @@ module JSONCop
6
6
  @name = name.gsub(/\s+/, "")
7
7
  @type = type.gsub(/\s+/, "")
8
8
  end
9
+
10
+ def real_type
11
+ return type[0..-2] if type.end_with? "?"
12
+ return type
13
+ end
14
+
15
+ def optional_type
16
+ return type if type.end_with? "?"
17
+ return type + "?"
18
+ end
19
+
20
+ def decode_type
21
+ built_in_types = %w[Int32 Int64 Bool Float Double]
22
+ return real_type if built_in_types.include? real_type
23
+
24
+ case real_type
25
+ when "Int" then "Integer"
26
+ when "Date" then "Object"
27
+ else "Object"
28
+ end
29
+ end
9
30
  end
10
31
  end
11
32
  end
@@ -2,6 +2,7 @@ module JSONCop
2
2
  module Model
3
3
  class Model
4
4
  attr_reader :name
5
+ attr_accessor :is_struct
5
6
  attr_accessor :attributes
6
7
  attr_accessor :transformers
7
8
  attr_accessor :attr_json_hash
@@ -0,0 +1,11 @@
1
+ module JSONCop
2
+ module Model
3
+ class Transformer
4
+ attr_reader :name, :type
5
+ def initialize(name, type)
6
+ @name = name.gsub(/\s+/, "")
7
+ @type = type.gsub(/\s+/, "").gsub(/:/, ": ")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module JSONCop
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsoncop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Draveness
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-19 00:00:00.000000000 Z
11
+ date: 2016-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: claide
@@ -126,6 +126,7 @@ files:
126
126
  - lib/jsoncop/helper.rb
127
127
  - lib/jsoncop/model/attribute.rb
128
128
  - lib/jsoncop/model/model.rb
129
+ - lib/jsoncop/model/transformer.rb
129
130
  - lib/jsoncop/version.rb
130
131
  homepage: https://github.com/Draveness/JSONCop
131
132
  licenses:
@@ -147,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
148
  version: '0'
148
149
  requirements: []
149
150
  rubyforge_project:
150
- rubygems_version: 2.6.4
151
+ rubygems_version: 2.6.6
151
152
  signing_key:
152
153
  specification_version: 4
153
154
  summary: A JSON to model method generator.