At the time of writing, I found that most of the popular frameworks (mostly network wrappers) when dealing with keypath do some terrible things.
So, suppose we have a Decodable (Codable) object but in the API response we are getting it under some custom path. Most of the solutions already have interface to extract object by keypath and also added Codable support. But the problem is that in almost all cases that I’ve seen implementation is next:
Extract [String: Any] from the Data with JSONSerialization
Follow keypath in this dictionary
Convert given object to Data
Use JSONDecoder to parse object
It is obvious that the conversion of data back and forth is an extra waste of resources. In addition, on large amounts of data, this is highly not advisable.
This package eliminates first 3 steps.
Usage
Say you have a Item model
struct Item: Codable {
...
}
And we have a following JSON:
{
"foo" : <actual object>
}
To parse this you need to write:
let jsonData: Data = ...
let item = try decoder.decode(Item.self, from: jsonData, keyPath: "foo")
Nested keypath are also supported:
let item = try decoder.decode(Item.self, from: jsonData, keyPath: "foo.bar")
func decode<T>(_ type: T.Type,
from data: Data,
keyPath: String,
keyPathSeparator separator: String = ".") throws -> T where T : Decodable
In this call keypath is stored in the JSONDecoder.userInfo and then standard decode method is called with private class KeyPathWrapper<T> as a type parameter. In the KeyPathWrapper constructor keypath data is fetched from the userInfo and decoder is traversed with this values. After that original type is decoded.
Installation
Swift Package Manager
Add the line .Package(url: "https://github.com/0111b/JSONDecoder-Keypath.git") to your Package.swift
Cocoapods
pod 'JSONDecoder-Keypath'
Conclusion
Mostly this is a naive implementation of the custom object encoding and took from me no more than a few hours. But it is showing that we must think how we are working with provided API’s and not be lazy to look under the hood
JSONDecoder-Keypath
Add nested key path support to the Foundation.JSONDecoder
Rationale
At the time of writing, I found that most of the popular frameworks (mostly network wrappers) when dealing with keypath do some terrible things.
So, suppose we have a
Decodable
(Codable
) object but in the API response we are getting it under some custom path. Most of the solutions already have interface to extract object by keypath and also addedCodable
support. But the problem is that in almost all cases that I’ve seen implementation is next:[String: Any]
from theData
withJSONSerialization
Data
JSONDecoder
to parse objectIt is obvious that the conversion of data back and forth is an extra waste of resources. In addition, on large amounts of data, this is highly not advisable.
This package eliminates first 3 steps.
Usage
Say you have a
Item
modelAnd we have a following JSON:
To parse this you need to write:
Nested keypath are also supported:
Keypath separator can be configured:
Under the hood
Package adds new method to the
JSONDecoder
In this call
keypath
is stored in theJSONDecoder.userInfo
and then standarddecode
method is called with private classKeyPathWrapper<T>
as a type parameter. In theKeyPathWrapper
constructor keypath data is fetched from theuserInfo
and decoder is traversed with this values. After that original type is decoded.Installation
Swift Package Manager
Add the line
.Package(url: "https://github.com/0111b/JSONDecoder-Keypath.git")
to yourPackage.swift
Cocoapods
Conclusion
Mostly this is a naive implementation of the custom object encoding and took from me no more than a few hours. But it is showing that we must think how we are working with provided API’s and not be lazy to look under the hood
Plans and improvements