@@ -18,34 +18,71 @@ import Foundation
1818/// Double, String, Bool,...) or a JSON object
1919@available ( iOS 15 . 0 , macOS 12 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
2020public struct AnyValue {
21- public private( set) var value : Data
21+ public var value : Data {
22+ do {
23+ let jsonEncoder = JSONEncoder ( )
24+ let data = try jsonEncoder. encode ( anyCodableValue)
25+ return data
26+ } catch {
27+ DataConnectLogger . logger. warning ( " Error encoding anyCodableValue \( error) " )
28+ return Data ( )
29+ }
30+ }
31+
32+ private var anyCodableValue : AnyCodableValue
2233
2334 public init ( codableValue: Codable ) throws {
2435 do {
25- let jsonEncoder = JSONEncoder ( )
26- value = try jsonEncoder. encode ( codableValue)
36+ if let int64Val = codableValue as? Int64 {
37+ anyCodableValue = . int64( int64Val)
38+ } else {
39+ // to recontruct JSON dictionary, one has to decode it from json data
40+ let jsonEncoder = JSONEncoder ( )
41+ let jsonData = try jsonEncoder. encode ( codableValue)
42+ let jsonDecoder = JSONDecoder ( )
43+ anyCodableValue = try jsonDecoder. decode ( AnyCodableValue . self, from: jsonData)
44+ }
2745 }
2846 }
2947
3048 public func decodeValue< T: Decodable > ( _ type: T . Type ) throws -> T ? {
3149 do {
32- let jsonDecoder = JSONDecoder ( )
33- let decodedResult = try jsonDecoder. decode ( type, from: value)
34- return decodedResult
50+ switch anyCodableValue {
51+ case let . int64( int64) :
52+ if type == Int64 . self {
53+ return int64 as? T
54+ } else {
55+ throw DataConnectCodecError . decodingFailed ( )
56+ }
57+ default :
58+ let jsonDecoder = JSONDecoder ( )
59+ let decodedResult = try jsonDecoder. decode ( type, from: value)
60+ return decodedResult
61+ }
3562 }
3663 }
3764}
3865
3966@available ( iOS 15 . 0 , macOS 12 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
4067extension AnyValue : Codable {
41- public init ( from decoder: any Decoder ) throws {
42- let singleValueContainer = try decoder. singleValueContainer ( )
43- value = try singleValueContainer. decode ( Data . self)
68+ public init ( from decoder: any Swift . Decoder ) throws {
69+ var container = try decoder. singleValueContainer ( )
70+ do {
71+ if let b64Data = try ? container. decode ( Data . self) {
72+ // backwards compatibility
73+ let jsonDecoder = JSONDecoder ( )
74+ anyCodableValue = try jsonDecoder. decode ( AnyCodableValue . self, from: b64Data)
75+ } else {
76+ let codecHelper = SingleValueCodecHelper ( )
77+ anyCodableValue = try codecHelper. decodeSingle ( AnyCodableValue . self, container: & container)
78+ }
79+ }
4480 }
4581
4682 public func encode( to encoder: any Encoder ) throws {
4783 var container = encoder. singleValueContainer ( )
48- try container. encode ( value)
84+ let codecHelper = SingleValueCodecHelper ( )
85+ try codecHelper. encodeSingle ( anyCodableValue, container: & container)
4986 }
5087}
5188
@@ -65,3 +102,75 @@ extension AnyValue: Hashable {
65102
66103@available ( iOS 15 . 0 , macOS 12 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
67104extension AnyValue : Sendable { }
105+
106+ // MARK: -
107+
108+ @available ( iOS 15 . 0 , macOS 12 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
109+ enum AnyCodableValue : Codable , Equatable {
110+ case string( String )
111+ case int64( Int64 )
112+ case number( Double )
113+ case bool( Bool )
114+ case dictionary( [ String : AnyCodableValue ] )
115+ case array( [ AnyCodableValue ] )
116+ case null
117+
118+ static func == ( lhs: AnyCodableValue , rhs: AnyCodableValue ) -> Bool {
119+ switch ( lhs, rhs) {
120+ case let ( . string( l) , . string( r) ) : return l == r
121+ case let ( . int64( l) , . int64( r) ) : return l == r
122+ case let ( . number( l) , . number( r) ) : return l == r
123+ case let ( . bool( l) , . bool( r) ) : return l == r
124+ case let ( . dictionary( l) , . dictionary( r) ) : return l == r
125+ case let ( . array( l) , . array( r) ) : return l == r
126+ case ( . null, . null) : return true
127+ default : return false
128+ }
129+ }
130+
131+ init ( from decoder: Decoder ) throws {
132+ let container = try decoder. singleValueContainer ( )
133+
134+ if let stringVal = try ? container. decode ( String . self) {
135+ if let int64Val = try ? Int64CodableConverter ( ) . decode ( input: stringVal) {
136+ self = . int64( int64Val)
137+ } else {
138+ self = . string( stringVal)
139+ }
140+ } else if let doubleVal = try ? container. decode ( Double . self) {
141+ self = . number( doubleVal)
142+ } else if let boolVal = try ? container. decode ( Bool . self) {
143+ self = . bool( boolVal)
144+ } else if let dictVal = try ? container. decode ( [ String : AnyCodableValue ] . self) {
145+ self = . dictionary( dictVal)
146+ } else if let arrayVal = try ? container. decode ( [ AnyCodableValue ] . self) {
147+ self = . array( arrayVal)
148+ } else if container. decodeNil ( ) {
149+ self = . null
150+ } else {
151+ throw DataConnectCodecError
152+ . decodingFailed ( message: " Error decode AnyCodableValue from \( container) " )
153+ }
154+ }
155+
156+ func encode( to encoder: Encoder ) throws {
157+ var container = encoder. singleValueContainer ( )
158+ switch self {
159+ case let . int64( value) :
160+ let encodedVal = try ? Int64CodableConverter ( ) . encode ( input: value)
161+ try container. encode ( encodedVal)
162+ case let . string( value) :
163+ try container. encode ( value)
164+ case let . number( value) :
165+ try container. encode ( value)
166+ case let . bool( value) :
167+ try container. encode ( value)
168+ case let . dictionary( value) :
169+ try container. encode ( value)
170+ case let . array( value) :
171+ try container. encode ( value)
172+ case . null:
173+ try container. encodeNil ( )
174+ }
175+ }
176+ }
0 commit comments