Skip to content

Commit 563be88

Browse files
committed
boxing array and object
1 parent 2be4817 commit 563be88

3 files changed

Lines changed: 246 additions & 28 deletions

File tree

README.md

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# TidyJSON
22
A neat and tidy JSON package run on all Swift platforms (Linux, iOS, OS X)
33

4-
Currently, JSON Array and Object are immutable
5-
64
## Goals
75
- [x] simple, neat and tidy json lib
8-
- [x] only dependent to builtin types
6+
- [x] safe static typed without `AnyObject`
7+
- [x] pure Swift, only dependent to builtin types
98
- [x] compatible with all Swift platforms (Linux, iOS, OS X)
109
- [x] concise usage
11-
- [ ] boxing dict and array type for mutating data
12-
- [ ] modify json via subscript operator
10+
- [x] boxing dict and array type for mutating data
11+
- [x] modify json via subscript operator
1312
- [x] fully tested
1413
- [x] better parse error report
1514
- [ ] Swift Package Manager, CocoaPods, Carthage support
@@ -27,6 +26,49 @@ let jsonArray : JSON = [12, "string", false, nil, true, ["nested array", 12, 1.2
2726
let json : JSON = ["key":false, "key2":true, "key3":[1, "hello", 3, "world", ["key4":nil, "key5":12.03, "key6":12E-2, "key7": -12e-2]]]
2827
```
2928

29+
### Update value
30+
```swift
31+
var json : JSON = []
32+
// []
33+
34+
let child :JSON = "string"
35+
json.append(child)
36+
// ["string"]
37+
38+
json[0] = "STRING"
39+
// ["STRING"]
40+
41+
json.append(JSON([]))
42+
// ["STRING", []]
43+
44+
json[1].append(JSON("hello"))
45+
// ["STRING", ["hello"]]
46+
47+
json[1][0] = "world"
48+
// ["STRING", ["world"]]
49+
50+
json[1].removeAtIndex(0)
51+
// ["STRING", []]
52+
53+
json.removeAtIndex(1)
54+
// ["STRING"]
55+
56+
var json1 : JSON = [:]
57+
// {}
58+
json1["hello"] = false
59+
// {"hello":false}
60+
61+
json1["world"] = true
62+
// {"hello":false, "world":true}
63+
64+
json1["hello"] = nil
65+
// {"world":true}
66+
67+
json1["world"] = [1,2,3]
68+
// {"world":[1,2,3]}
69+
```
70+
71+
3072
### Parse from String
3173
```swift
3274
let json1 = JSON.parse("{\"key\" : false }")
@@ -92,5 +134,23 @@ On Linux platform you need install [`XCTest`](https://github.com/apple/swift-cor
92134

93135
After install `XCTest`, run `sh run_test.sh`
94136

137+
## Integration
138+
139+
#### Swift Package Manager
140+
141+
Currently support Swift Package Manager to install TidyJSON by adding the proper description to your Package.swift file:
142+
143+
```swift
144+
import PackageDescription
145+
146+
let package = Package(
147+
name: "YOUR_PROJECT_NAME",
148+
targets: [],
149+
dependencies: [
150+
.Package(url: "https://github.com/benloong/TidyJSON.git", majorVersion: 1)
151+
]
152+
)
153+
```
154+
95155
## License
96156
MIT license

Sources/JSON.swift

Lines changed: 129 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,60 @@
1+
2+
13
public enum JSON {
2-
// empty json or invalid json with parse error message
4+
/**
5+
* Box wrapper for array value
6+
*/
7+
public class _ArrayBox {
8+
var array : [JSON]
9+
init(_ a: [JSON]) {
10+
array = a
11+
}
12+
}
13+
14+
/**
15+
* Box wrapper for object value
16+
*/
17+
public class _DictBox {
18+
var dict: [Swift.String : JSON]
19+
init(_ d: [Swift.String : JSON]) {
20+
dict = d
21+
}
22+
}
23+
24+
/**
25+
* Empty json or invalid json with parse error message
26+
*/
327
case None(_: Swift.String?)
28+
29+
/**
30+
* JSON null value
31+
*/
432
case Null
33+
34+
/**
35+
* JSON bool value(true, false)
36+
*/
537
case Boolean(_: Bool)
38+
39+
/**
40+
* JSON number value
41+
*/
642
case Number(_: Double)
43+
44+
/**
45+
* JSON string value
46+
*/
747
case String(_: Swift.String)
8-
case Array(_: [JSON])
9-
case Object(_: [Swift.String : JSON])
48+
49+
/**
50+
* JSON array value
51+
*/
52+
case Array(_: _ArrayBox)
53+
54+
/**
55+
* JSON object value
56+
*/
57+
case Object(_: _DictBox)
1058

1159
init() {
1260
self = .None(nil)
@@ -35,6 +83,10 @@ extension JSON : BooleanLiteralConvertible {
3583
self = .Boolean(value)
3684
}
3785

86+
public init(_ b: Bool) {
87+
self = .Boolean(b)
88+
}
89+
3890
/**
3991
* Boolean value of this JSON, only for bool value
4092
*/
@@ -51,6 +103,14 @@ extension JSON : FloatLiteralConvertible {
51103
self = .Number(Double(value))
52104
}
53105

106+
public init(_ value: Double) {
107+
self = .Number(value)
108+
}
109+
110+
public init(_ value: Float) {
111+
self = .Number(Double(value))
112+
}
113+
54114
/**
55115
* Double floating value of this JSON, only for number value
56116
*/
@@ -76,6 +136,10 @@ extension JSON : IntegerLiteralConvertible {
76136
public init(integerLiteral value: IntegerLiteralType) {
77137
self = .Number(Double(value))
78138
}
139+
140+
public init(_ value: Int) {
141+
self = .Number(Double(value))
142+
}
79143

80144
/**
81145
* Integer value of this JSON, only for number value
@@ -106,7 +170,7 @@ extension JSON : StringLiteralConvertible {
106170
}
107171

108172
/**
109-
* string value of this JSON, only null, string, true, false, number values has value
173+
* string value of this JSON, only null, string, true, false, number values not nil
110174
*/
111175
public var string : Swift.String? {
112176
switch self {
@@ -125,22 +189,42 @@ extension JSON : ArrayLiteralConvertible {
125189
for e in elements {
126190
array.append(e)
127191
}
128-
self = .Array(array)
192+
self = .Array(_ArrayBox(array))
129193
}
130194

131195
public init(_ array: [JSON]) {
132-
self = .Array(array)
196+
self = .Array(_ArrayBox(array))
133197
}
134198

135199
/**
136200
* Internal Array container of this JSON
137201
*/
138202
public var array : [JSON]? {
139203
switch self {
140-
case .Array(let x): return x
204+
case .Array(let x): return x.array
141205
default: return nil
142206
}
143207
}
208+
209+
/**
210+
* Append newElement to the Array JSON.
211+
*/
212+
public func append(newElement: JSON) {
213+
switch self {
214+
case .Array(let x): x.array.append(newElement)
215+
default: break
216+
}
217+
}
218+
219+
/**
220+
* Remove and return the child json at index i.
221+
*/
222+
public func removeAtIndex(index: Int) -> JSON {
223+
switch self {
224+
case .Array(let x): return x.array.removeAtIndex(index)
225+
default: return JSON()
226+
}
227+
}
144228
}
145229

146230
extension JSON : DictionaryLiteralConvertible {
@@ -150,19 +234,19 @@ extension JSON : DictionaryLiteralConvertible {
150234
dict[k] = v
151235
}
152236

153-
self = .Object(dict)
237+
self = .Object(_DictBox(dict))
154238
}
155239

156240
public init(_ dict: [Swift.String : JSON]) {
157-
self = .Object(dict)
241+
self = .Object(_DictBox(dict))
158242
}
159243

160244
/**
161245
* Internal Dictionary container of this JSON
162246
*/
163247
public var object : [Swift.String : JSON]? {
164248
switch self {
165-
case .Object(let x): return x
249+
case .Object(let x): return x.dict
166250
default: return nil
167251
}
168252
}
@@ -179,8 +263,8 @@ extension JSON : SequenceType {
179263
*/
180264
public var count : Int {
181265
switch self {
182-
case .Object(let obj): return obj.count
183-
case .Array(let arr): return arr.count
266+
case .Object(let obj): return obj.dict.count
267+
case .Array(let arr): return arr.array.count
184268
default: return 0
185269
}
186270
}
@@ -199,8 +283,8 @@ extension JSON : SequenceType {
199283
var index : Int = 0
200284
init(json: JSON) {
201285
switch json {
202-
case .Object(let obj): objectGenerator = obj.generate()
203-
case .Array(let arr): arrayGenerator = arr.generate()
286+
case .Object(let obj): objectGenerator = obj.dict.generate()
287+
case .Array(let arr): arrayGenerator = arr.array.generate()
204288
default: break
205289
}
206290
}
@@ -222,16 +306,39 @@ extension JSON : SequenceType {
222306
//MARK: - subscript
223307
extension JSON {
224308
public subscript(i : Int) -> JSON {
225-
switch self {
226-
case .Array(let a): return a[i]
227-
default: return JSON()
309+
get {
310+
switch self {
311+
case .Array(let a): return a.array[i]
312+
default: return JSON()
313+
}
314+
}
315+
316+
set {
317+
switch self {
318+
case .Array(let a): a.array[i] = newValue
319+
default: break
320+
}
228321
}
229322
}
230323

231324
public subscript(key : Swift.String) -> JSON {
232-
switch self {
233-
case .Object(let o): return o[key] ?? JSON()
234-
default: return JSON()
325+
get {
326+
switch self {
327+
case .Object(let o): return o.dict[key] ?? nil
328+
default: return JSON()
329+
}
330+
}
331+
set {
332+
switch self {
333+
case .Object(let o):
334+
if newValue.isNull {
335+
o.dict[key] = nil
336+
}
337+
else {
338+
o.dict[key] = newValue
339+
}
340+
default: break
341+
}
235342
}
236343
}
237344
}
@@ -266,8 +373,8 @@ extension JSON {
266373
case .Boolean(let b) : string.appendContentsOf(b.description)
267374
case .Number(let n) : string.appendContentsOf(n.description)
268375
case .String(let s) : dumpString(&string, jsonString: s)
269-
case .Array(let a) : dumpArray(&string, array: a)
270-
case .Object(let o) : dumpObject(&string, object: o)
376+
case .Array(let a) : dumpArray(&string, array: a.array)
377+
case .Object(let o) : dumpObject(&string, object: o.dict)
271378
}
272379
}
273380

0 commit comments

Comments
 (0)