'How to filter sensitive data server-side for object based on scenario
Scenario:
- Class
Example, subclassed fromPFObject. Some sensitive properties are optional/can be nil. - User A creates examples locally on the client and saves it directly to the server (with ACL set to this user only)
- User B should only see a subset of this data.
My approach:
- create a cloud code function
getExamplefor User B to call getExamplequeries those examples, deletes all sensitive properties on the results (or recreates the object with only allowed properties) and returns those filtered objects.
Problem:
- Whats the best approach to tell the parse engine that the return value is actually of type
Exampleand make it parse it automatically? (call to server is viaPFCloud.callFunction(inBackground: ...))?
Thank you (also, any architecture advise highly appreciated).
Solution 1:[1]
Decoding backend JSON responses in Swift is almost trivial nowadays, with the Decodable protocol and the JSONDecoder class from the Foundation library.
Here's an example with an optional field:
import Foundation
let jsonString1 = """
{
"stringField" : "stringValue",
"intField" : 1,
"floatField" : 1.1
}
"""
let jsonString2 = """
{
"stringField" : "stringValue",
"intField" : 1,
"floatField" : 1.1,
"optionalField" : "optionalValue"
}
"""
struct Response: Decodable {
let stringField: String
let intField: Int
let floatField: Double
let optionalField: String?
}
let response1 = try! JSONDecoder().decode(Response.self, from: jsonString1.data(using: .utf8)!)
// Response(stringField: "stringValue", intField: 1, floatField: 1.1, optionalField: nil)
let response2 = try! JSONDecoder().decode(Response.self, from: jsonString2.data(using: .utf8)!)
// Response(stringField: "stringValue", intField: 1, floatField: 1.1, optionalField: Optional("optionalValue"))
And one more example, with a nested object:
import Foundation
let jsonString = """
{
"stringField" : "stringValue",
"nestedObject" :
{
"intValue" : 2
}
}
"""
struct Response: Decodable {
struct NestedType: Decodable {
let intValue: Int
}
let stringField: String
let nestedObject: NestedType
}
let response = try! JSONDecoder().decode(Response.self, from: jsonString.data(using: .utf8)!)
// Response(stringField: "stringValue", nestedObject: __lldb_expr_10.Response.NestedType(intValue: 2))
An example with a date:
import Foundation
let jsonString = """
{
"date" : "2021-02-04 09:38:33.000"
}
"""
struct Response: Decodable {
let date: Date
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let response = try! decoder.decode(Response.self, from: jsonString.data(using: .utf8)!)
// Response(date: 2021-02-04 09:38:33 +0000)
Find out more here.
UPDATE
After discussion it became clear that the problem is that the object to parse is a dictionary containing objects that cannot be represented in JSON natively (e.g. Data/NSData). In this case it's possible to convert them into something representable (e.g. for dates it can be a formatted String). Here's an example involving NSDate and JSONSerialization:
import Foundation
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let jsonDict1 = ["stringField" : "stringValue"]
let jsonData1 = try JSONSerialization.data(withJSONObject: jsonDict1)
let date = NSDate()
let jsonDict2: [String : Any] = ["stringField" : "stringValue",
"optionalDate" : dateFormatter.string(from: date as Date)]
let jsonData2 = try JSONSerialization.data(withJSONObject: jsonDict2)
struct Response: Decodable {
let stringField: String
let optionalDate: Date?
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let response1 = try! decoder.decode(Response.self, from: jsonData1)
// Response(stringField: "stringValue", optionalDate: nil)
let response2 = try! decoder.decode(Response.self, from: jsonData2)
// Response(stringField: "stringValue", optionalDate: Optional(2022-02-21 13:48:48 +0000))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
