Skip to content

Commit 32822f0

Browse files
authored
fix(amplify_datastore): iOS json deserialization (#806)
iOS ONLY fix. Android was unaffected. Ensure nested model int types are returned as int instead of double Consolidate duplicated code for extracting values from Json during serialization step
1 parent 7ff6000 commit 32822f0

File tree

1 file changed

+67
-106
lines changed

1 file changed

+67
-106
lines changed

packages/amplify_datastore/ios/Classes/types/model/FlutterSerializedModel.swift

Lines changed: 67 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -74,51 +74,59 @@ struct FlutterSerializedModel: Model, JSONValueHolder {
7474
try x.encode(values)
7575
}
7676

77-
public func jsonValue(for key: String) -> Any?? {
78-
if key == "id" {
79-
return id
80-
}
81-
switch values[key] {
82-
case .some(.array(let deserializedValue)):
77+
internal func jsonValue(for key: String) -> Any?? {
78+
return FlutterSerializedModel.extractJsonValue(value: values[key])
79+
}
80+
81+
internal func jsonValue(for key: String, modelSchema: ModelSchema) -> Any?? {
82+
return FlutterSerializedModel.extractJsonValue(key: key, value: values[key], modelSchema: modelSchema)
83+
}
84+
85+
private static func extractJsonValue(value: JSONValue?) -> Any?? {
86+
guard let value = value else { return nil }
87+
88+
switch value {
89+
case .array(let deserializedValue):
8390
return deserializedValue
84-
case .some(.boolean(let deserializedValue)):
91+
case .boolean(let deserializedValue):
8592
return deserializedValue
86-
case .some(.number(let deserializedValue)):
93+
case .number(let deserializedValue):
8794
return deserializedValue
88-
case .some(.object(let deserializedValue)):
95+
case .object(let deserializedValue):
8996
return deserializedValue
90-
case .some(.string(let deserializedValue)):
97+
case .string(let deserializedValue):
9198
return deserializedValue
92-
case .some(.null):
93-
return nil
94-
case .none:
99+
case .null:
95100
return nil
96101
}
97102
}
98103

99-
public func jsonValue(for key: String, modelSchema: ModelSchema) -> Any?? {
100-
let field = modelSchema.field(withName: key)
101-
if case .int = field?.type,
102-
case .some(.number(let deserializedValue)) = values[key] {
103-
return Int(deserializedValue)
104-
} else if case .dateTime = field?.type,
105-
case .some(.string(let deserializedValue)) = values[key] {
106-
return FlutterTemporal(iso8601String: deserializedValue)
107-
} else if case .date = field?.type,
108-
case .some(.string(let deserializedValue)) = values[key] {
109-
return FlutterTemporal(iso8601String: deserializedValue)
110-
} else if case .time = field?.type,
111-
case .some(.string(let deserializedValue)) = values[key] {
112-
return FlutterTemporal(iso8601String: deserializedValue)
113-
} else if case .timestamp = field?.type,
114-
case .some(.number(let deserializedValue)) = values[key] {
115-
return NSNumber(value: deserializedValue)
116-
}
104+
private static func extractJsonValue(key: String, value: JSONValue?, modelSchema: ModelSchema, returnTemporalType: Bool = true) -> Any?? {
117105

118-
return jsonValue(for: key)
106+
let field = modelSchema.field(withName: key)
107+
switch (field?.type, value) {
108+
case (.int, .number(let deserializedValue)):
109+
return Int(deserializedValue)
110+
case (.dateTime, .string(let deserializedValue)), (.date, .string(let deserializedValue)), (.time, .string(let deserializedValue)):
111+
112+
// If returning value for Amplify iOS library return FlutterTemporal
113+
if(returnTemporalType) {
114+
return FlutterTemporal(iso8601String: deserializedValue)
115+
}
116+
// Else returning value to be serialized to Flutter layer
117+
else{
118+
return deserializedValue
119+
}
120+
121+
case (.timestamp, .number(let deserializedValue)):
122+
return Int(deserializedValue)
123+
default:
124+
return extractJsonValue(value: value);
125+
}
119126
}
120127

121-
private func deserializeValue(value: JSONValue?, fieldType: Codable.Type) -> Any?? {
128+
private static func deserializeValue(value: JSONValue?, fieldType: Codable.Type) -> Any?? {
129+
122130
if fieldType is Int.Type,
123131
case .some(.number(let deserializedValue)) = value {
124132
return Int(deserializedValue)
@@ -166,92 +174,45 @@ struct FlutterSerializedModel: Model, JSONValueHolder {
166174
throw error
167175
}
168176
}
169-
170-
private static func generateSerializedJsonData(values: [String: JSONValue], flutterModelRegistration: FlutterModels, modelName: String) throws -> [String: Any] {
171-
let modelSchema = try getModelSchema(flutterModelRegistration: flutterModelRegistration, modelName: modelName)
172-
var result = [String: Any]()
173-
174-
for (key, value) in values {
175-
let field = modelSchema.field(withName: key)
176-
if case .object(let deserializedValue) = value {
177-
// If a field that has many models
178-
if (deserializedValue["associatedField"] != nil && deserializedValue["associatedId"] != nil) {
179-
result[key] = nil
180-
}
181-
// If a field that has one or belongs to a model
182-
else if case .string(let modelId) = deserializedValue["id"],
183-
case .model(let nextModelName) = field!.type {
184-
result[key] = [
185-
"id": modelId,
186-
"modelName": nextModelName,
187-
"serializedData": try generateSerializedJsonData(values: deserializedValue, flutterModelRegistration: flutterModelRegistration, modelName: nextModelName)
188-
]
189-
}
190-
} else if case .string(let deserializedValue) = value {
191-
result[key] = deserializedValue
192-
} else if case .boolean(let deserializedValue) = value {
193-
result[key] = deserializedValue
194-
} else if case .number(let deserializedValue) = value {
195-
result[key] = deserializedValue
196-
} else if case .null = value {
197-
result[key] = nil
198-
}
199-
}
200-
201-
return result;
202-
}
203-
204-
private func generateSerializedData(flutterModelRegistration: FlutterModels, modelName: String) throws -> [String: Any]{
177+
178+
private static func generateSerializedData(values: [String: JSONValue], flutterModelRegistration: FlutterModels, modelName: String) throws -> [String: Any]{
205179
let modelSchema = try FlutterSerializedModel.getModelSchema(flutterModelRegistration: flutterModelRegistration, modelName: modelName)
206180
var result = [String: Any]()
207181

208182
for(key, value) in values {
209183
let field = modelSchema.field(withName: key)
210-
184+
211185
if(value == nil){
212186
continue
213187
}
214188

215-
if case .model = field?.type{
216-
let map = jsonValue(for: key, modelSchema: modelSchema) as! [String: JSONValue]
217-
if case .string(let modelId) = map["id"],
218-
case .model(let modelName) = field!.type
219-
{
220-
result[key] = [
221-
"id": modelId,
222-
"modelName": modelName,
223-
"serializedData": try FlutterSerializedModel.generateSerializedJsonData(values: map, flutterModelRegistration: flutterModelRegistration, modelName: modelName)
224-
]
225-
}
226-
} else if case .collection = field?.type{
189+
if case .object(let deserializedValue) = value {
190+
// If a field that has many models
191+
if (deserializedValue["associatedField"] != nil && deserializedValue["associatedId"] != nil) {
192+
result[key] = nil;
193+
}
194+
// If a field that has one or belongs to a model
195+
else if case .string(let modelId) = deserializedValue["id"],
196+
case .model(let nextModelName) = field!.type {
197+
result[key] = [
198+
"id": modelId,
199+
"modelName": nextModelName,
200+
"serializedData": try generateSerializedData(values: deserializedValue, flutterModelRegistration: flutterModelRegistration, modelName: nextModelName)
201+
]
202+
}
203+
}
204+
205+
else if case .collection = field?.type{
227206
continue
228207
} else if case .embeddedCollection(let fieldType, _) = field?.type{
229208
if case .array(let jsonArray) = value {
230-
var modifiedArray:[Any??] = []
231-
for item in jsonArray {
232-
let parsedItem = deserializeValue(value: item, fieldType: fieldType)
233-
modifiedArray.append(parsedItem)
209+
result[key] = jsonArray.map {
210+
deserializeValue(value: $0, fieldType: fieldType)
234211
}
235-
result[key] = modifiedArray
236212
}
237-
} else if case .dateTime = field?.type,
238-
case .some(.string(let deserializedValue)) = values[key] {
239-
240-
result[key] = deserializedValue
241-
} else if case .date = field?.type,
242-
case .some(.string(let deserializedValue)) = values[key] {
243-
244-
result[key] = deserializedValue
245-
} else if case .time = field?.type,
246-
case .some(.string(let deserializedValue)) = values[key] {
247-
248-
result[key] = deserializedValue
249-
} else if case .timestamp = field?.type,
250-
case .some(.number(let deserializedValue)) = values[key] {
251-
252-
result[key] = NSNumber(value: Int(deserializedValue) )
253-
} else {
254-
result[key] = jsonValue(for: key, modelSchema: modelSchema)!
213+
}
214+
else {
215+
result[key] = extractJsonValue(key: key, value: values[key], modelSchema: modelSchema, returnTemporalType: false)!
255216
}
256217
}
257218

@@ -262,7 +223,7 @@ struct FlutterSerializedModel: Model, JSONValueHolder {
262223
return [
263224
"id": id,
264225
"modelName": modelName,
265-
"serializedData": try generateSerializedData(flutterModelRegistration: flutterModelRegistration, modelName: modelName)
226+
"serializedData": try FlutterSerializedModel.generateSerializedData(values: self.values, flutterModelRegistration: flutterModelRegistration, modelName: modelName)
266227
]
267228
}
268229
}

0 commit comments

Comments
 (0)