@@ -19,57 +19,156 @@ import FoundationEssentials
19
19
import Foundation
20
20
#endif
21
21
22
- public struct JSON : Codable , @unchecked Sendable { // FIXME: make Sendable
23
- public var value : Any ?
22
+ public enum JSONValue : Codable , Sendable {
23
+ case null
24
+ case int( Int )
25
+ case double( Double )
26
+ case string( String )
27
+ case bool( Bool )
28
+ case array( [ JSONValue ] )
29
+ case object( [ String : JSONValue ] )
30
+
31
+ public init ( _ value: Any ? ) {
32
+
33
+ guard let value else {
34
+ self = . null
35
+ return
36
+ }
37
+ switch value {
38
+ case let v as Int :
39
+ self = . int( v)
40
+ break
41
+ case let v as Double :
42
+ self = . double( v)
43
+ break
44
+ case let v as String :
45
+ self = . string( v)
46
+ break
47
+ case let v as Bool :
48
+ self = . bool( v)
49
+ break
50
+ case let v as [ Any ] :
51
+ self = . array( v. map { JSONValue ( $0) } )
52
+ break
53
+ case let v as [ String : JSONValue ] :
54
+ self = . object( v)
55
+ break
56
+ case let v as [ JSONValue ] :
57
+ self = . array( v)
58
+ break
59
+ case let v as JSONValue :
60
+ self = v
61
+ break
62
+ default :
63
+ fatalError ( " JSONValue: Unsupported type: \( type ( of: value) ) " )
64
+ }
65
+ }
24
66
25
- /// Returns the value inside the JSON object defined by the given key.
26
67
public subscript< T> ( key: String ) -> T ? {
27
68
get {
28
- if let dictionary = value as? [ String : JSON ] {
29
- let json : JSON ? = dictionary [ key]
30
- let nestedValue : Any ? = json? . getValue ( )
31
- return nestedValue as? T
69
+ if case let . object( dictionary) = self {
70
+ guard let jsonValue = dictionary [ key] else {
71
+ return nil
72
+ }
73
+ switch jsonValue {
74
+ case . int( let v) : return v as? T
75
+ case . double( let v) : return v as? T
76
+ case . string( let v) : return v as? T
77
+ case . bool( let v) : return v as? T
78
+ case . array( let v) : return v as? T
79
+ case . object( let v) : return v as? T
80
+ case . null: return nil
81
+ }
32
82
}
33
83
return nil
34
84
}
35
85
}
36
86
37
- /// Returns the JSON object defined by the given key.
38
- public subscript( key: String ) -> JSON ? {
87
+ public init ( from decoder: Decoder ) throws {
88
+ let container = try decoder. singleValueContainer ( )
89
+ if container. decodeNil ( ) {
90
+ self = . null
91
+ } else if let intValue = try ? container. decode ( Int . self) {
92
+ self = . int( intValue)
93
+ } else if let doubleValue = try ? container. decode ( Double . self) {
94
+ self = . double( doubleValue)
95
+ } else if let stringValue = try ? container. decode ( String . self) {
96
+ self = . string( stringValue)
97
+ } else if let boolValue = try ? container. decode ( Bool . self) {
98
+ self = . bool( boolValue)
99
+ } else if let arrayValue = try ? container. decode ( [ JSONValue ] . self) {
100
+ self = . array( arrayValue)
101
+ } else if let dictionaryValue = try ? container. decode ( [ String : JSONValue ] . self) {
102
+ self = . object( dictionaryValue)
103
+ } else {
104
+ throw DecodingError . dataCorruptedError ( in: container, debugDescription: " Unsupported type " )
105
+ }
106
+ }
107
+
108
+ // MARK: Public Methods
109
+
110
+ public func encode( to encoder: Encoder ) throws {
111
+ var container = encoder. singleValueContainer ( )
112
+ switch self {
113
+ case . null:
114
+ try container. encodeNil ( )
115
+ case . int( let v) :
116
+ try container. encode ( v)
117
+ case . double( let v) :
118
+ try container. encode ( v)
119
+ case . string( let v) :
120
+ try container. encode ( v)
121
+ case . bool( let v) :
122
+ try container. encode ( v)
123
+ case . array( let v) :
124
+ try container. encode ( v)
125
+ case . object( let v) :
126
+ try container. encode ( v)
127
+ }
128
+ }
129
+
130
+ }
131
+
132
+ public struct JSON : Codable , Sendable {
133
+ public let value : JSONValue
134
+
135
+ public subscript< T> ( key: String ) -> T ? {
39
136
get {
40
- if let dictionary = value as? [ String : JSON ] {
41
- return dictionary [ key]
42
- }
43
- return nil
137
+ value [ key]
44
138
}
45
139
}
46
140
47
- /// Returns the value inside the JSON object defined by the given key.
48
- public func getValue< T> ( _ key: String ) -> T ? {
49
- if let dictionary = value as? [ String : JSON ] {
50
- return dictionary [ key] ? . value as? T
141
+ public subscript( key: String ) -> JSONValue ? {
142
+ get {
143
+ if case let . object( dictionary) = value {
144
+ if let v = dictionary [ key] {
145
+ return v
146
+ }
147
+ }
148
+ return nil
51
149
}
52
- return nil
53
150
}
54
151
55
- /// Returns the value inside the JSON object.
56
152
public func getValue< T> ( ) -> T ? {
57
- value as? T
153
+ switch value {
154
+ case . int( let v) : return v as? T
155
+ case . double( let v) : return v as? T
156
+ case . string( let v) : return v as? T
157
+ case . bool( let v) : return v as? T
158
+ case . array( let v) : return v as? T
159
+ case . object( let v) : return v as? T
160
+ case . null: return nil
161
+ }
58
162
}
59
163
60
164
// MARK: Initializers
61
165
62
- public init ( with value: Any ? ) {
166
+ public init ( with value: JSONValue ) {
63
167
self . value = value
64
168
}
65
169
66
170
public init ( from string: String ) throws {
67
- var s : String !
68
- if string. isEmpty {
69
- s = " {} "
70
- } else {
71
- s = string
72
- }
171
+ let s = string. isEmpty ? " {} " : string
73
172
guard let data = s. data ( using: . utf8) else {
74
173
throw BedrockLibraryError . encodingError ( " Could not encode String to Data " )
75
174
}
@@ -78,59 +177,18 @@ public struct JSON: Codable, @unchecked Sendable { // FIXME: make Sendable
78
177
79
178
public init ( from data: Data ) throws {
80
179
do {
180
+ print ( String ( decoding: data, as: UTF8 . self) )
81
181
self = try JSONDecoder ( ) . decode ( JSON . self, from: data)
82
182
} catch {
83
183
throw BedrockLibraryError . decodingError ( " Failed to decode JSON: \( error) " )
84
184
}
85
185
}
86
186
187
+ // Codable
188
+
87
189
public init ( from decoder: Decoder ) throws {
88
190
let container = try decoder. singleValueContainer ( )
89
- if container. decodeNil ( ) {
90
- self . value = nil
91
- } else if let intValue = try ? container. decode ( Int . self) {
92
- self . value = intValue
93
- } else if let doubleValue = try ? container. decode ( Double . self) {
94
- self . value = doubleValue
95
- } else if let stringValue = try ? container. decode ( String . self) {
96
- self . value = stringValue
97
- } else if let boolValue = try ? container. decode ( Bool . self) {
98
- self . value = boolValue
99
- } else if let arrayValue = try ? container. decode ( [ JSON ] . self) {
100
- self . value = arrayValue. map { JSON ( with: $0. value) }
101
- } else if let dictionaryValue = try ? container. decode ( [ String : JSON ] . self) {
102
- self . value = dictionaryValue. mapValues { JSON ( with: $0. value) }
103
- } else {
104
- throw DecodingError . dataCorruptedError ( in: container, debugDescription: " Unsupported type " )
105
- }
191
+ value = try container. decode ( JSONValue . self)
106
192
}
107
193
108
- // MARK: Public Methods
109
-
110
- public func encode( to encoder: Encoder ) throws {
111
- var container = encoder. singleValueContainer ( )
112
- if let jsonValue = value as? JSON {
113
- try jsonValue. encode ( to: encoder)
114
- } else if let intValue = value as? Int {
115
- try container. encode ( intValue)
116
- } else if let doubleValue = value as? Double {
117
- try container. encode ( doubleValue)
118
- } else if let stringValue = value as? String {
119
- try container. encode ( stringValue)
120
- } else if let boolValue = value as? Bool {
121
- try container. encode ( boolValue)
122
- } else if let arrayValue = value as? [ Any ] {
123
- let jsonArray = arrayValue. map { JSON ( with: $0) }
124
- try container. encode ( jsonArray)
125
- } else if let dictionaryValue = value as? [ String : Any ] {
126
- let jsonDictionary = dictionaryValue. mapValues { JSON ( with: $0) }
127
- try container. encode ( jsonDictionary)
128
- } else {
129
- // try container.encode(String(describing: value ?? "nil"))
130
- throw EncodingError . invalidValue (
131
- value ?? " nil " ,
132
- EncodingError . Context ( codingPath: encoder. codingPath, debugDescription: " Unsupported type " )
133
- )
134
- }
135
- }
136
194
}
0 commit comments