Library / SDK
alibaba/HandyJSON avatar
alibaba/HandyJSON

HandyJSON: reflection-based JSON mapping for Swift classes and structs

GitHub describes it as A handy swift json-object serialization/deserialization library. The repository metadata lists Swift as its primary language. The metadata lists the NOASSERTION license. This article stays within the project description and details documented in the GitHub repository README.

4,256 stars677 forksSwiftNOASSERTION

At a glance

What is it?
HandyJSON maps JSON to Swift models without NSObject inheritance or a mapping function, by writing values straight into memory. The last push was on 2018-07-27, so the version you pin matters more than the feature list.
Who is it for?
HandyJSON fits projects that already have plain Swift model types and want JSON mapping without NSObject inheritance or hand-written mapping code, and that can pin an exact version and test it on the Xcode and Swift release they ship with. It is the wrong choice for new code that can adopt Codable, and for anyone who needs a library receiving regular maintenance: the last push was on 2018-07-27 and the latest release is 4.1.3.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Probably not. The repository last received commits 31 months ago, on March 8, 2024.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem HandyJSON removes: NSObject and mapping functions

Most Swift JSON libraries of its generation ask for one of two things. Either your model inherits from NSObject so the library can use KVC, or you write a mapping function that names every property and its JSON key. HandyJSON's README states the difference plainly: it "does not require the objects inherit from NSObject (not using KVC but reflection), neither implements a 'mapping' function (writing value to memory directly to achieve property assignment)".

That matters when your models are plain Swift classes or structs and you do not want a Foundation base class in the type hierarchy. It also matters when the JSON keys already match your property names, because then there is nothing to declare. The library is aimed at iOS, macOS, watchOS and tvOS applications, per the requirements section, and supports Swift structs as well as classes, which a KVC-based design cannot do.

The trade is explicit in the README: "HandyJSON is totally depend on the memory layout rules infered from Swift runtime code." A library that writes into memory directly is coupled to the compiler's layout decisions, not to a documented public API. That sentence is the whole risk model of the project.

How deserialization works: reflection plus direct memory writes

A type opts in by conforming to the HandyJSON protocol. Classes must implement an empty initializer, marked required. Structs get the compiler's default empty initializer for free, unless you have declared a designated initializer, in which case the README says you must declare an empty one yourself, without the required modifier.

At runtime the library reads the JSON, inspects the type's property layout through Swift's reflection facilities, and assigns values by writing to the memory offsets those properties occupy. There is no intermediate NSDictionary step and no per-property mapping table. Nested types, arrays, dictionaries, optionals and implicitly unwrapped optionals are handled by the same mechanism, and the README points to HandyJSONTest/BasicTypes.swift for the full list of supported property types.

Enums need a separate conformance. An enum must adopt HandyJSONEnum to be convertible; the README's example uses a String raw value and reads the result back through rawValue. Type adaptation is supported too, so a string JSON field can land in an Int property and the reverse, which saves you from writing custom transforms for the common case of loosely typed backend payloads. Custom mapping and designated paths exist for the cases where the shape does not match.

Installing HandyJSON and mapping your first model

Version selection is the first real decision, because the README ties library versions to Swift versions. It states that Swift 5.0/5.1 with Xcode 10.2+/11.0+ needs version 5.0.2, Swift 4.2 with Xcode 10 needs 4.2.0, Swift 4.0 needs 4.1.1 or later, and Swift 3.x needs 1.8.0 or later. Pick the line that matches your toolchain before you touch a package manager.

With CocoaPods, add the dependency to your Podfile and install:

ruby
pod 'HandyJSON', '~> 5.0.2'
bash
$ pod install

Carthage users add a single line to the Cartfile instead:

code
github "alibaba/HandyJSON" ~> 5.0.2

The repository also ships Package.swift and [email protected], so Swift Package Manager consumers have manifests to point at, and the manual route uses a git submodule plus dragging HandyJSON.xcodeproj into the project navigator and embedding the framework that matches your platform.

Once it is linked, the smallest working model is a class with an empty initializer. The README's example deserializes a JSON string and prints three properties:

swift
class BasicTypes: HandyJSON {
    var int: Int = 2
    var doubleOptional: Double?
    var stringImplicitlyUnwrapped: String!

    required init() {}
}

let jsonString = "{\"doubleOptional\":1.1,\"stringImplicitlyUnwrapped\":\"hello\",\"int\":1}"
if let object = BasicTypes.deserialize(from: jsonString) {
    print(object.int)
    print(object.doubleOptional!)
    print(object.stringImplicitlyUnwrapped)
}

Serialization runs the other way, from an instance back to a dictionary or a JSON string:

swift
let object = BasicTypes()
object.int = 1
object.doubleOptional = 1.1
object.stringImplicitlyUnwrapped = "hello"

print(object.toJSON()!)          // dictionary
print(object.toJSONString()!)    // JSON string

If the prints match your input, the reflection path is working for your toolchain. If they do not, the version table is the first place to look.

The memory layout dependency is the failure mode

Because property assignment bypasses the compiler's own type checking, a mismatch between the library's assumptions and the runtime's layout does not produce a Swift error. It produces a crash or corrupted values. The README itself opens with a warning of exactly this kind: to deal with a crash on iOS 15 beta3, try version 5.0.4-beta. That is a beta tag offered as the fix for a platform-level break, and it is not listed among the recent releases, whose newest entry is 4.1.3 from 2018-07-27.

The last push to the default branch was on 2018-07-27. For a library whose stated design premise is following the Swift runtime's memory layout "every bit if it changes", an eight-year gap between that premise and current toolchains is the central fact to weigh. The README's own version table stops at Swift 5.0/5.1, and there is no documented support statement for later Swift releases.

There is a second, quieter limitation. Type adaptation and automatic key matching mean typos and shape changes fail silently rather than loudly: a JSON field that does not map to any property is simply not written, and a value that cannot be adapted leaves the property at its default. That convenience is real, and so is the debugging cost when a field quietly does not appear.

Codable is the alternative, and the difference is where the work happens

Swift's own Codable, built on Encodable and Decodable with JSONDecoder and JSONEncoder from Foundation, solves the same problem from the opposite direction. It uses compiler-synthesized code rather than runtime reflection and memory writes, so the mapping is generated at build time and checked by the compiler. A missing key or a type mismatch throws a DecodingError instead of corrupting memory.

The cost of that safety is conformance work. You declare CodingKeys when JSON names differ from property names, and you write custom init(from:) when the shape does not match. HandyJSON's pitch is that you skip that work entirely for the common case where names already line up. Codable also requires the type to be Decodable, which for classes means an initializer that the synthesized code can call, and it will not reach into a type that does not opt in.

So the choice is not about capability. Both map JSON to Swift models. Codable moves the effort to compile time and gives you errors; HandyJSON moves it to runtime and gives you less code. For a codebase that already has plain models and no appetite for writing CodingKeys across dozens of types, that difference is the reason to consider HandyJSON at all.

Maintenance, version pinning and licence status

The repository is not archived, but the last push was on 2018-07-27, and the newest release in the list is 4.1.3 from the same date. The README's installation section points at 5.0.2 for Swift 5.0/5.1 and mentions a 5.0.4-beta for the iOS 15 beta3 crash, so the release list and the README are not describing the same set of versions. That gap is worth resolving before you commit to a version line: check the tags on the repository rather than assuming the README's numbers are published releases.

Upgrade cost is dominated by the Swift version table. Moving your project to a newer Swift release means checking whether a HandyJSON version exists for it, and the README's table ends at Swift 5.0/5.1. If no matching version exists, the upgrade path is a fork or a migration to Codable, which is a rewrite of every model's conformance rather than a dependency bump.

The licence is recorded as NOASSERTION in the repository metadata, and a LICENSE file is present at the top level. NOASSERTION means the automated classifier could not match the file to a known licence identifier, so read the LICENSE file itself and confirm the terms with whoever handles licensing on your team before shipping. Nothing here is legal advice; the point is that the metadata does not answer the question for you.

Editorial conclusion

HandyJSON fits projects that already have plain Swift model types and want JSON mapping without NSObject inheritance or hand-written mapping code, and that can pin an exact version and test it on the Xcode and Swift release they ship with. It is the wrong choice for new code that can adopt Codable, and for anyone who needs a library receiving regular maintenance: the last push was on 2018-07-27 and the latest release is 4.1.3. Before adopting, verify the version matching your Swift toolchain against the README's table, confirm the package resolves through the Package.swift and [email protected] manifests, and run your own model types through deserialize and toJSONString on your target OS versions.

Frequently asked questions

Does HandyJSON require models to inherit from NSObject?

No. The README states that HandyJSON does not require objects to inherit from NSObject and does not use KVC, relying on reflection and direct writes to memory instead. Classes must implement an empty initializer marked required.

Which HandyJSON version should I use with my Swift version?

The README maps Swift 5.0/5.1 with Xcode 10.2+/11.0+ to version 5.0.2, Swift 4.2 with Xcode 10 to 4.2.0, Swift 4.0 to 4.1.1 or later, and Swift 3.x to 1.8.0 or later. The table does not cover Swift releases after 5.1.

Can HandyJSON deserialize into Swift structs and enums?

Structs are supported; the README notes they use the compiler's default empty initializer unless you have declared a designated one, in which case you declare an empty initializer yourself. Enums must conform to HandyJSONEnum to be convertible.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/alibaba-handyjson.svg)](https://hysenlabs.com/projects/alibaba-handyjson)