Convert Figma logo to code with AI

SwiftyJSON logoSwiftyJSON

The better way to deal with JSON data in Swift.

22,755
3,431
22,755
137

Top Related Projects

Simple JSON Object mapping written in Swift

41,446

Elegant HTTP Networking in Swift

Convenient & secure logging during development & release in Swift 4 & 5

15,190

Network abstraction layer written in Swift.

Quick Overview

SwiftyJSON is a popular Swift library that simplifies the handling of JSON data in iOS and macOS applications. It provides an easy-to-use interface for parsing, manipulating, and generating JSON, making it more convenient than working with Swift's built-in JSON handling methods.

Pros

  • Simplifies JSON parsing and manipulation with a clean, intuitive API
  • Supports type-safe access to JSON data
  • Reduces boilerplate code and potential for errors when working with JSON
  • Actively maintained and widely adopted in the Swift community

Cons

  • May introduce a dependency for a task that can be accomplished with native Swift libraries
  • Performance might be slightly slower compared to manual JSON parsing in some cases
  • Learning curve for developers already familiar with Swift's native JSON handling
  • Limited to JSON data format, not suitable for other data formats

Code Examples

  1. Parsing JSON from a string:
let json = JSON(parseJSON: """
{
    "name": "John Doe",
    "age": 30,
    "city": "New York"
}
""")

print(json["name"].stringValue) // Output: John Doe
print(json["age"].intValue) // Output: 30
  1. Creating JSON:
var json = JSON()
json["name"].string = "Jane Smith"
json["age"].int = 28
json["hobbies"].arrayObject = ["reading", "swimming"]

print(json) // Output: {"name":"Jane Smith","age":28,"hobbies":["reading","swimming"]}
  1. Working with arrays:
let jsonArray = JSON(parseJSON: """
[
    {"name": "Alice", "score": 95},
    {"name": "Bob", "score": 80},
    {"name": "Charlie", "score": 90}
]
""")

for (index, student) in jsonArray.arrayValue.enumerated() {
    print("\(index + 1). \(student["name"].stringValue): \(student["score"].intValue)")
}

Getting Started

  1. Add SwiftyJSON to your project using Swift Package Manager:

  2. Import SwiftyJSON in your Swift file:

import SwiftyJSON
  1. Start using SwiftyJSON to work with JSON data:
let json = JSON(["name": "John", "age": 30])
print(json["name"].stringValue)

Competitor Comparisons

Simple JSON Object mapping written in Swift

Pros of ObjectMapper

  • Supports custom transformations for complex property types
  • Allows for nested object mapping
  • Provides a more type-safe approach to JSON parsing

Cons of ObjectMapper

  • Requires more setup and boilerplate code
  • Slightly steeper learning curve for beginners
  • May be overkill for simple JSON structures

Code Comparison

ObjectMapper:

class User: Mappable {
    var name: String?
    var age: Int?
    
    required init?(map: Map) {}
    
    func mapping(map: Map) {
        name <- map["name"]
        age  <- map["age"]
    }
}

SwiftyJSON:

if let json = try? JSON(data: jsonData) {
    let name = json["name"].stringValue
    let age = json["age"].intValue
}

ObjectMapper requires defining a mapping structure for each object, which provides more control but requires more code. SwiftyJSON offers a simpler, more direct approach to accessing JSON values, making it easier to use for basic JSON parsing tasks. However, ObjectMapper's approach is more scalable for complex data structures and provides better type safety. The choice between the two libraries depends on the specific requirements of your project and the complexity of the JSON data you're working with.

41,446

Elegant HTTP Networking in Swift

Pros of Alamofire

  • Comprehensive networking library with features beyond JSON parsing
  • Supports various HTTP methods, authentication, and request/response handling
  • Active development and community support

Cons of Alamofire

  • Larger library size, may be overkill for simple JSON parsing needs
  • Steeper learning curve due to more extensive API

Code Comparison

SwiftyJSON:

if let json = try? JSON(data: responseData) {
    let name = json["name"].stringValue
    let age = json["age"].intValue
}

Alamofire:

AF.request("https://api.example.com/data").responseJSON { response in
    if let json = response.value as? [String: Any] {
        let name = json["name"] as? String ?? ""
        let age = json["age"] as? Int ?? 0
    }
}

Key Differences

  • SwiftyJSON focuses solely on JSON parsing, while Alamofire is a full-featured networking library
  • Alamofire requires more setup but offers more functionality for complex networking tasks
  • SwiftyJSON provides a simpler API for JSON manipulation, making it easier to use for basic JSON handling

Use Cases

  • Choose SwiftyJSON for projects primarily focused on JSON parsing and manipulation
  • Opt for Alamofire when building applications that require comprehensive networking capabilities beyond JSON handling

Convenient & secure logging during development & release in Swift 4 & 5

Pros of SwiftyBeaver

  • Focused on logging and debugging, providing a more specialized toolset
  • Offers multiple destinations for logs (console, file, cloud)
  • Supports custom log formats and filters

Cons of SwiftyBeaver

  • Limited to logging functionality, not as versatile for general data handling
  • May require additional setup for cloud logging features

Code Comparison

SwiftyBeaver:

import SwiftyBeaver
let log = SwiftyBeaver.self
log.addDestination(ConsoleDestination())
log.info("Hello World")

SwiftyJSON:

import SwiftyJSON
let json = JSON(["name": "John", "age": 30])
print(json["name"].stringValue)

Summary

SwiftyBeaver is a specialized logging framework for Swift, offering advanced logging features and multiple output destinations. It's ideal for developers who need robust logging capabilities in their projects. On the other hand, SwiftyJSON is a JSON parsing library that simplifies working with JSON data in Swift. While SwiftyBeaver excels in logging, SwiftyJSON is more versatile for handling JSON data structures. The choice between the two depends on the specific needs of your project: logging (SwiftyBeaver) or JSON manipulation (SwiftyJSON).

15,190

Network abstraction layer written in Swift.

Pros of Moya

  • Provides a higher level of abstraction for network requests, simplifying API integration
  • Offers built-in support for testing and stubbing network calls
  • Encourages a more modular and maintainable codebase through its target-based approach

Cons of Moya

  • Has a steeper learning curve due to its more complex architecture
  • May be overkill for simple projects with minimal networking requirements
  • Requires additional setup and configuration compared to SwiftyJSON

Code Comparison

Moya:

let provider = MoyaProvider<MyAPI>()
provider.request(.userProfile) { result in
    switch result {
    case let .success(response):
        let data = response.data
        // Process data
    case let .failure(error):
        // Handle error
    }
}

SwiftyJSON:

if let data = response.data {
    let json = JSON(data)
    let name = json["name"].stringValue
    let age = json["age"].intValue
    // Use parsed data
}

While SwiftyJSON focuses on JSON parsing, Moya provides a complete networking abstraction layer. SwiftyJSON is simpler to use for basic JSON handling, while Moya offers more robust features for complex API interactions.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

SwiftyJSON

Carthage compatible CocoaPods Platform Reviewed by Hound

SwiftyJSON makes it easy to deal with JSON data in Swift.

PlatformBuild Status
*OSTravis CI
LinuxBuild Status
  1. Why is the typical JSON handling in Swift NOT good
  2. Requirements
  3. Integration
  4. Usage
  5. Work with Alamofire
  6. Work with Moya
  7. SwiftyJSON Model Generator

Why is the typical JSON handling in Swift NOT good?

Swift is very strict about types. But although explicit typing is good for saving us from mistakes, it becomes painful when dealing with JSON and other areas that are, by nature, implicit about types.

Take the Twitter API for example. Say we want to retrieve a user's "name" value of some tweet in Swift (according to Twitter's API).

The code 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 {
    // Finally we got the username
}

It's not good.

Even if we use optional chaining, it would be messy:

if let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
    let username = (JSONObject[0]["user"] as? [String: Any])?["name"] as? String {
        // There's our username
}

An unreadable mess--for something that should really be simple!

With SwiftyJSON all you have to do is:

let json = try? JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
  //Now you got your value
}

And don't worry about the Optional Wrapping thing. It's done for you automatically.

let json = try? JSON(data: dataFromNetworking)
let result = json[999999]["wrong_key"]["wrong_name"]
if let userName = result.string {
    //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
} else {
    //Print the error
    print(result.error)
}

Requirements

  • iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+
  • Xcode 8

Integration

CocoaPods (iOS 8+, OS X 10.9+)

You can use CocoaPods to install SwiftyJSON by adding it to your Podfile:

platform :ios, '8.0'
use_frameworks!

target 'MyApp' do
    pod 'SwiftyJSON', '~> 4.0'
end

Carthage (iOS 8+, OS X 10.9+)

You can use Carthage to install SwiftyJSON by adding it to your Cartfile:

github "SwiftyJSON/SwiftyJSON" ~> 4.0

If you use Carthage to build your dependencies, make sure you have added SwiftyJSON.framework to the "Linked Frameworks and Libraries" section of your target, and have included them in your Carthage framework copying build phase.

Swift Package Manager

You can use The Swift Package Manager to install SwiftyJSON by adding the proper description to your Package.swift file:

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "YOUR_PROJECT_NAME",
    dependencies: [
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),
    ]
)

Then run swift build whenever you get prepared.

Manually (iOS 7+, OS X 10.9+)

To use this library in your project manually you may:

  1. for Projects, just drag SwiftyJSON.swift to the project tree
  2. for Workspaces, include the whole SwiftyJSON.xcodeproj

Usage

Initialization

import SwiftyJSON
let json = try? JSON(data: dataFromNetworking)

Or

let json = JSON(jsonObject)

Or

if let dataFromString = jsonString.data(using: .utf8, allowLossyConversion: false) {
    let json = JSON(data: dataFromString)
}

Subscript

// Getting a double from a JSON Array
let name = json[0].double
// Getting an array of string from a JSON Array
let arrayNames =  json["users"].arrayValue.map {$0["name"].stringValue}
// Getting a string from a JSON Dictionary
let name = json["name"].stringValue
// Getting a string using a path to the element
let path: [JSONSubscriptType] = [1,"list",2,"name"]
let name = json[path].string
// Just the same
let name = json[1]["list"][2]["name"].string
// Alternatively
let name = json[1,"list",2,"name"].string
// With a hard way
let name = json[].string
// With a custom way
let keys:[JSONSubscriptType] = [1,"list",2,"name"]
let name = json[keys].string

Loop

// If json is .Dictionary
for (key,subJson):(String, JSON) in json {
   // Do something you want
}

The first element is always a String, even if the JSON is an Array

// If json is .Array
// The `index` is 0..<json.count's string value
for (index,subJson):(String, JSON) in json {
    // Do something you want
}

Error

SwiftyJSON 4.x

SwiftyJSON 4.x introduces an enum type called SwiftyJSONError, which includes unsupportedType, indexOutOfBounds, elementTooDeep, wrongType, notExist and invalidJSON, at the same time, ErrorDomain are being replaced by SwiftyJSONError.errorDomain. Note: Those old error types are deprecated in SwiftyJSON 4.x and will be removed in the future release.

SwiftyJSON 3.x

Use a subscript to get/set a value in an Array or Dictionary

If the JSON is:

  • an array, the app may crash with "index out-of-bounds."
  • a dictionary, it will be assigned to nil without a reason.
  • not an array or a dictionary, the app may crash with an "unrecognised selector" exception.

This will never happen in SwiftyJSON.

let json = JSON(["name", "age"])
if let name = json[999].string {
    // Do something you want
} else {
    print(json[999].error!) // "Array[999] is out of bounds"
}
let json = JSON(["name":"Jack", "age": 25])
if let name = json["address"].string {
    // Do something you want
} else {
    print(json["address"].error!) // "Dictionary["address"] does not exist"
}
let json = JSON(12345)
if let age = json[0].string {
    // Do something you want
} else {
    print(json[0])       // "Array[0] failure, It is not an array"
    print(json[0].error!) // "Array[0] failure, It is not an array"
}

if let name = json["name"].string {
    // Do something you want
} else {
    print(json["name"])       // "Dictionary[\"name"] failure, It is not an dictionary"
    print(json["name"].error!) // "Dictionary[\"name"] failure, It is not an dictionary"
}

Optional getter

// NSNumber
if let id = json["user"]["favourites_count"].number {
   // Do something you want
} else {
   // Print the error
   print(json["user"]["favourites_count"].error!)
}
// String
if let id = json["user"]["name"].string {
   // Do something you want
} else {
   // Print the error
   print(json["user"]["name"].error!)
}
// Bool
if let id = json["user"]["is_translator"].bool {
   // Do something you want
} else {
   // Print the error
   print(json["user"]["is_translator"].error!)
}
// Int
if let id = json["user"]["id"].int {
   // Do something you want
} else {
   // Print the error
   print(json["user"]["id"].error!)
}
...

Non-optional getter

Non-optional getter is named xxxValue

// If not a Number or nil, return 0
let id: Int = json["id"].intValue
// If not a String or nil, return ""
let name: String = json["name"].stringValue
// If not an Array or nil, return []
let list: Array<JSON> = json["list"].arrayValue
// If not a Dictionary or nil, return [:]
let user: Dictionary<String, JSON> = json["user"].dictionaryValue

Setter

json["name"] = JSON("new-name")
json[0] = JSON(1)
json["id"].int =  1234567890
json["coordinate"].double =  8766.766
json["name"].string =  "Jack"
json.arrayObject = [1,2,3,4]
json.dictionaryObject = ["name":"Jack", "age":25]

Raw object

let rawObject: Any = json.object
let rawValue: Any = json.rawValue
//convert the JSON to raw NSData
do {
	let rawData = try json.rawData()
  //Do something you want
} catch {
	print("Error \(error)")
}
//convert the JSON to a raw String
if let rawString = json.rawString() {
  //Do something you want
} else {
	print("json.rawString is nil")
}

Existence

// shows you whether value specified in JSON or not
if json["name"].exists()

Literal convertibles

For more info about literal convertibles: Swift Literal Convertibles

// StringLiteralConvertible
let json: JSON = "I'm a json"
// IntegerLiteralConvertible
let json: JSON =  12345
// BooleanLiteralConvertible
let json: JSON =  true
// FloatLiteralConvertible
let json: JSON =  2.8765
// DictionaryLiteralConvertible
let json: JSON =  ["I":"am", "a":"json"]
// ArrayLiteralConvertible
let json: JSON =  ["I", "am", "a", "json"]
// With subscript in array
var json: JSON =  [1,2,3]
json[0] = 100
json[1] = 200
json[2] = 300
json[999] = 300 // Don't worry, nothing will happen
// With subscript in dictionary
var json: JSON =  ["name": "Jack", "age": 25]
json["name"] = "Mike"
json["age"] = "25" // It's OK to set String
json["address"] = "L.A." // Add the "address": "L.A." in json
// Array & Dictionary
var json: JSON =  ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]]
json["list"][3]["what"] = "that"
json["list",3,"what"] = "that"
let path: [JSONSubscriptType] = ["list",3,"what"]
json[path] = "that"
// With other JSON objects
let user: JSON = ["username" : "Steve", "password": "supersecurepassword"]
let auth: JSON = [
  "user": user.object, // use user.object instead of just user
  "apikey": "supersecretapitoken"
]

Merging

It is possible to merge one JSON into another JSON. Merging a JSON into another JSON adds all non existing values to the original JSON which are only present in the other JSON.

If both JSONs contain a value for the same key, mostly this value gets overwritten in the original JSON, but there are two cases where it provides some special treatment:

  • In case of both values being a JSON.Type.array the values form the array found in the other JSON getting appended to the original JSON's array value.
  • In case of both values being a JSON.Type.dictionary both JSON-values are getting merged the same way the encapsulating JSON is merged.

In a case where two fields in a JSON have different types, the value will get always overwritten.

There are two different fashions for merging: merge modifies the original JSON, whereas merged works non-destructively on a copy.

let original: JSON = [
    "first_name": "John",
    "age": 20,
    "skills": ["Coding", "Reading"],
    "address": [
        "street": "Front St",
        "zip": "12345",
    ]
]

let update: JSON = [
    "last_name": "Doe",
    "age": 21,
    "skills": ["Writing"],
    "address": [
        "zip": "12342",
        "city": "New York City"
    ]
]

let updated = original.merge(with: update)
// [
//     "first_name": "John",
//     "last_name": "Doe",
//     "age": 21,
//     "skills": ["Coding", "Reading", "Writing"],
//     "address": [
//         "street": "Front St",
//         "zip": "12342",
//         "city": "New York City"
//     ]
// ]

Removing elements

If you are storing dictionaries, you can remove elements using dictionaryObject.removeValue(forKey:). This mutates the JSON object in place.

For example:

var object = JSON([
    "one": ["color": "blue"],
    "two": ["city": "tokyo",
            "country": "japan",
            "foods": [
                "breakfast": "tea",
                "lunch": "sushi"
                ]
            ]
])

Lets remove the country key:

object["two"].dictionaryObject?.removeValue(forKey: "country")

If you print(object), you'll see that the country key no longer exists.

{
  "one" : {
    "color" : "blue"
  },
  "two" : {
    "city" : "tokyo",
    "foods" : {
      "breakfast" : "tea",
      "lunch" : "sushi"
    }
  }
}

This also works for nested dictionaries:

object["two"]["foods"].dictionaryObject?.removeValue(forKey: "breakfast")
{
  "one" : {
    "color" : "blue"
  },
  "two" : {
    "city" : "tokyo",
    "foods" : {
      "lunch" : "sushi"
    }
  }
}

String representation

There are two options available:

  • use the default Swift one
  • use a custom one that will handle optionals well and represent nil as "null":
let dict = ["1":2, "2":"two", "3": nil] as [String: Any?]
let json = JSON(dict)
let representation = json.rawString(options: [.castNilToNSNull: true])
// representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null}

Work with Alamofire

SwiftyJSON nicely wraps the result of the Alamofire JSON response handler:

Alamofire.request(url, method: .get).validate().responseJSON { response in
    switch response.result {
    case .success(let value):
        let json = JSON(value)
        print("JSON: \(json)")
    case .failure(let error):
        print(error)
    }
}

We also provide an extension of Alamofire for serializing NSData to SwiftyJSON's JSON.

See: Alamofire-SwiftyJSON

Work with Moya

SwiftyJSON parse data to JSON:

let provider = MoyaProvider<Backend>()
provider.request(.showProducts) { result in
    switch result {
    case let .success(moyaResponse):
        let data = moyaResponse.data
        let json = JSON(data: data) // convert network data to json
        print(json)
    case let .failure(error):
        print("error: \(error)")
    }
}

SwiftyJSON Model Generator

Tools to generate SwiftyJSON Models