Swift4 JSON to Object or Object to JSON
BaseJson4 makes you more easier to transform data type from JSON to Object or reverse.</br> *support only Swift 4 and above
We want to handle data which is JSON string getting from backend with service API, we have to useDictionary
orArray
to transform or parse data in to the model, until Swift 4 Codable
introduced.
The BaseJson4 base on new protocolCodable
could let you more easier to useCodable
feature and more clean your own code and more importantly reduce low-level errors by hands with autocomplete.
Handle the object property rather than handle a string [“user”] make Xcode to check is it correct.
With BaseJson4 just use User Object, User could be Class or Struct all you have to do this:
if let user = jsonStr.toObj(type: User.self) {
print("userName= \(user.name)")
let age = user.age
}
With official Apple Example would look like this:
if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
let user = statusesArray[0]["user"] as? [String: Any],
let userName = user["name"] as? String {
print("userName= \(user.name)")
}
With SwiftyJSON would look like this:
let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
print("userName= \(user.name)")
}
see, BaseJson4 more clean right?
iOS 9.0+ | macOS 10.10+ |
You can use CocoaPods to installBaseJson4
by adding it to yourPodfile
:
platform :ios, '9.0'
use_frameworks!
target 'MyApp' do
pod 'BaseJson4'
end
To use this library in your project manually you may:
Here is a Json string
{"id":66, "birthday":"1997-05-08", "height": 180.61, "name":"kittymo", "gender":"M", "age": 29, "friends": [ {"name":"Bill", "isFriend": true}, {"name":"Allen", "isFriend": false, "test":1} ]}
First of all create the object Model, in here we using class, of course you can using struct if you want.
class User: BaseJson4 {
var name: String? = nil
var gender: String? = nil
var age: Int = 0
var birthday: String? = nil
var friends: [Friend]? = nil
var height: Double = 0
}
class Friend: BaseJson4 {
var name: String? = nil
var isFriend: Bool = false
}
The String
/Data
has beenextension
by BaseJson4 with methodtoObj
Source of Json data types could beString
orData
you can use like this code follow:
let jsonStr = "{"id":66, "birthday":"1997-05-08", "height": 180.61, "name":"kittymo", "gender":"M", "age": 29, "friends": [ {"name":"Bill", "isFriend": true}, {"name":"Allen", "isFriend": false, "test":1} ]}"
if let user = jsonStr.toObj(type: User.self) {
let desc = user.description() // description() method can print all of properties in this object
print("Object content ==> \(desc)")
// .... just use this obeject
let age = user.age
let name = user.name
if let friends = user.friends {
for friend in friends {
print("friend name=\(friend.name)")
}
}
}
Just one line code, String.toObj
, we succeed transform from a Json string to an object Model
here is output log on console follow:
Object content ==>
<User:
name=Optional("kittymo")
gender=Optional("M")
age=29
birthday=Optional("1997-05-08")
friends=Array count=2 [ <Friend: name=Optional("Bill") isFriend=true>, <Friend: name=Optional("Allen") isFriend=false> ]
height=180.61
>
friend name=Optional("Bill")
friend name=Optional("Allen")
Is it easy, right?
Remember Json string has a property named birthday
, it’s a birthday date, we want to it’s data typs can transform from String
to Data
Object.
Here is show you how to do that follow:
Just change two place (where comment) follow:
class User: BaseJson4 {
var name: String? = nil
var gender: String? = nil
var age: Int = 0
var birthday: Date? = nil // <--- change type annotation here from String to Data
var friends: [Friend]? = nil
var height: Double = 0
static func dateFormats() -> [String: String]? {
return [CodingKeys.birthday.stringValue: "yyyy-MM-dd"] // <--- define date format you want like: yyyy-MM-dd
}
}
That’s it, property birthday
is became Date
date type! yeh!
after modify the output log on console follow
Object content ==>
<User:
name=Optional("kittymo")
gender=Optional("M")
age=29
birthday=Optional(1997-05-07 16:00:00 +0000)
friends=Array count=2 [ <Friend: name=Optional("Bill") isFriend=true>, <Friend: name=Optional("Allen") isFriend=false> ]
height=180.61
>
How do we do transform from an Object
to Json string
?.
Well, it’s very simple, just one line code.
let jsonStr = user.toJson()
print("json string = \(jsonStr)")
the output log on console follow:
json string = {"age":29,"gender":"M","friends":[{"name":"Bill","isFriend":true},{"name":"Allen","isFriend":false}],"name":"kittymo","birthday":"1997-05-08","height":180.61000000000001}
It is suitable way if for machine read with default format
If you want to print out Json format for human read, add the argument like user.toJson(.prettyPrinted)
let jsonStr = user.toJson(.prettyPrinted) // <--- modify by argument: prettyPrinted
the output will be nice to human read, log on console follow:
json string = {
"age" : 29,
"gender" : "M",
"friends" : [
{
"name" : "Bill",
"isFriend" : true
},
{
"name" : "Allen",
"isFriend" : false
}
],
"name" : "kittymo",
"birthday" : "1997-05-08",
"height" : 180.61000000000001
}
When we get Json string which is not Swift style, we want to modify that to be Swift style, you can using different name mapping here is show you how to do different name mapping way.
{"user_id":66, "user_name":"阿媛", "valid":true, "sex":"F", "style":"村菇"}
We want let the columnuser_name
to be name
, user_id
to be userId
ModifyUser
object model, and add CodingKeys like follow:
class User: BaseJson4 {
var userId: Int = 0
var name: String? = nil
var gender: String? = nil
var valid: Bool = false
var style: String? = nil
// Reset CodingKeys to do different name mapping
enum CodingKeys : String, CodingKey {
case userId = "user_id" // different name mapping
case name = "user_name" // different name mapping
case gender = "sex" // different name mapping
case valid // same name
case style // same name
}
}
Notice: if you have reset CodingKeys
to do different name mapping, all of properties must be set with same name, Do not be ignored if the column name is the same name.
The method Json -> Object just the same before: ```swift let jsonStr = "{\"user_id\":66, \"user_name\":\"阿媛\", \"valid\":true, \"sex\":\"F\", \"style\":\"村菇\"}" print("input json string ==> \(jsonStr)") // json string --> Object if let user = jsonStr.toObj(type: User.self) { let desc = user.description() print("Object content ==> \(desc)") // Object --> json string let ss = user.toJson(.prettyPrinted) print("json string = \(ss)") } ``` the output log on console follow: ```text input json string ==> {"user_id":66, "user_name":"阿媛", "valid":true, "sex":"F", "style":"村菇"} Object content ==> <User: userId=66 name=Optional("阿媛") gender=Optional("F") valid=true style=Optional("村菇") > json string = { "sex" : "F", "style" : "村菇", "user_id" : 66, "valid" : true, "user_name" : "阿媛" } ``` Just rename the column name, it's perfect mapping in to the object model. Translated by TerryCK