mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Add playground page showing off sparse fieldset encoding
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
|
||||
import JSONAPI
|
||||
import Foundation
|
||||
|
||||
// MARK: - Resource Object
|
||||
|
||||
enum ThingWithPropertiesDescription: JSONAPI.ResourceObjectDescription {
|
||||
static let jsonType: String = "thing"
|
||||
|
||||
//
|
||||
// NOTE: `JSONAPI.SparsableAttributes` as opposed to `JSONAPI.Attributes`
|
||||
//
|
||||
struct Attributes: JSONAPI.SparsableAttributes {
|
||||
let stringThing: Attribute<String>
|
||||
let numberThing: Attribute<Double>
|
||||
let boolThing: Attribute<Bool?>
|
||||
|
||||
//
|
||||
// NOTE: Special implementation of `CodingKeys`
|
||||
//
|
||||
enum CodingKeys: String, JSONAPI.SparsableCodingKey {
|
||||
case stringThing
|
||||
case numberThing
|
||||
case boolThing
|
||||
}
|
||||
}
|
||||
|
||||
typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
typealias ThingWithProperties = JSONAPI.ResourceObject<ThingWithPropertiesDescription, NoMetadata, NoLinks, String>
|
||||
|
||||
// MARK: - Document
|
||||
|
||||
//
|
||||
// NOTE: Using `JSONAPI.EncodableResourceBody` which means the document type will be `Encodable` but not `Decodable`.
|
||||
//
|
||||
typealias Document<PrimaryResourceBody: JSONAPI.EncodableResourceBody, IncludeType: JSONAPI.Include> = JSONAPI.Document<PrimaryResourceBody, NoMetadata, NoLinks, IncludeType, NoAPIDescription, UnknownJSONAPIError>
|
||||
|
||||
//
|
||||
// NOTE: Using `JSONAPI.EncodablePrimaryResource` which means the `ResourceBody` will be `Encodable` but not `Decodable.
|
||||
//
|
||||
typealias SingleDocument<T: JSONAPI.EncodablePrimaryResource> = Document<SingleResourceBody<T>, NoIncludes>
|
||||
|
||||
// MARK: - Resource Initialization
|
||||
|
||||
let resource = ThingWithProperties(id: .init(rawValue: "1234"),
|
||||
attributes: .init(stringThing: .init(value: "hello world"),
|
||||
numberThing: .init(value: 10),
|
||||
boolThing: .init(value: nil)),
|
||||
relationships: .none,
|
||||
meta: .none,
|
||||
links: .none)
|
||||
//
|
||||
// NOTE: Creating a sparse resource that will only encode
|
||||
// the attribute named "stringThing"
|
||||
//
|
||||
let sparseResource = resource.sparse(with: [.stringThing])
|
||||
|
||||
// MARK: - Encoding
|
||||
|
||||
let encoder = JSONEncoder()
|
||||
|
||||
let sparseResourceDoc = SingleDocument(apiDescription: .none,
|
||||
body: .init(resourceObject: sparseResource),
|
||||
includes: .none,
|
||||
meta: .none,
|
||||
links: .none)
|
||||
|
||||
let data = try! encoder.encode(sparseResourceDoc)
|
||||
|
||||
print(String(data: data, encoding: .utf8)!)
|
||||
@@ -8,6 +8,7 @@ Please enjoy these examples, but allow me the forced casting and the lack of err
|
||||
|
||||
********/
|
||||
|
||||
|
||||
// MARK: - Create a request or response body with one Dog in it
|
||||
let dogFromCode = try! Dog(name: "Buddy", owner: nil)
|
||||
|
||||
@@ -15,17 +16,20 @@ let singleDogDocument = SingleDogDocument(apiDescription: .none, body: .init(res
|
||||
|
||||
let singleDogData = try! JSONEncoder().encode(singleDogDocument)
|
||||
|
||||
|
||||
// MARK: - Parse a request or response body with one Dog in it
|
||||
let dogResponse = try! JSONDecoder().decode(SingleDogDocument.self, from: singleDogData)
|
||||
let dogFromData = dogResponse.body.primaryResource?.value
|
||||
let dogOwner: Person.Identifier? = dogFromData.flatMap { $0 ~> \.owner }
|
||||
|
||||
// MARKL - Parse a request or response body with one Dog in it using an alternative model
|
||||
|
||||
// MARK: - Parse a request or response body with one Dog in it using an alternative model
|
||||
typealias AltSingleDogDocument = JSONAPI.Document<SingleResourceBody<AlternativeDog>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>
|
||||
let altDogResponse = try! JSONDecoder().decode(AltSingleDogDocument.self, from: singleDogData)
|
||||
let altDogFromData = altDogResponse.body.primaryResource?.value
|
||||
let altDogHuman: Person.Identifier? = altDogFromData.flatMap { $0 ~> \.human }
|
||||
|
||||
|
||||
// MARK: - Create a request or response with multiple people and dogs and houses included
|
||||
let personIds = [Person.Identifier(), Person.Identifier()]
|
||||
let dogs = try! [Dog(name: "Buddy", owner: personIds[0]), Dog(name: "Joy", owner: personIds[0]), Dog(name: "Travis", owner: personIds[1])]
|
||||
@@ -36,6 +40,7 @@ let includes = dogs.map { BatchPeopleDocument.Include($0) } + houses.map { Batch
|
||||
let batchPeopleDocument = BatchPeopleDocument(apiDescription: .none, body: .init(resourceObjects: people), includes: .init(values: includes), meta: .none, links: .none)
|
||||
let batchPeopleData = try! JSONEncoder().encode(batchPeopleDocument)
|
||||
|
||||
|
||||
// MARK: - Parse a request or response body with multiple people in it and dogs and houses included
|
||||
|
||||
let peopleResponse = try! JSONDecoder().decode(BatchPeopleDocument.self, from: batchPeopleData)
|
||||
@@ -47,6 +52,7 @@ print("-----")
|
||||
print(peopleResponse)
|
||||
print("-----")
|
||||
|
||||
|
||||
// MARK: - Pass successfully parsed body to other parts of the code
|
||||
|
||||
/*
|
||||
@@ -59,6 +65,7 @@ if case let .data(bodyData) = peopleResponse.body {
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// MARK: - Work in the abstract
|
||||
|
||||
func process<T: JSONAPIDocument>(document: T) {
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
<page name='Usage'/>
|
||||
<page name='Full Client & Server Example'/>
|
||||
<page name='Full Document Verbose Generation'/>
|
||||
<page name='Sparse Fieldsets Example'/>
|
||||
</pages>
|
||||
</playground>
|
||||
@@ -144,6 +144,10 @@ extension DocumentTests {
|
||||
("test_singleDocumentSomeIncludesWithMetadata_encode", test_singleDocumentSomeIncludesWithMetadata_encode),
|
||||
("test_singleDocumentSomeIncludesWithMetadataWithAPIDescription", test_singleDocumentSomeIncludesWithMetadataWithAPIDescription),
|
||||
("test_singleDocumentSomeIncludesWithMetadataWithAPIDescription_encode", test_singleDocumentSomeIncludesWithMetadataWithAPIDescription_encode),
|
||||
("test_sparseIncludeFullPrimaryResource", test_sparseIncludeFullPrimaryResource),
|
||||
("test_sparseIncludeSparsePrimaryResource", test_sparseIncludeSparsePrimaryResource),
|
||||
("test_sparsePrimaryResource", test_sparsePrimaryResource),
|
||||
("test_sparsePrimaryResourceOptionalAndNil", test_sparsePrimaryResourceOptionalAndNil),
|
||||
("test_unknownErrorDocumentAddIncludes", test_unknownErrorDocumentAddIncludes),
|
||||
("test_unknownErrorDocumentAddIncludingType", test_unknownErrorDocumentAddIncludingType),
|
||||
("test_unknownErrorDocumentMissingLinks", test_unknownErrorDocumentMissingLinks),
|
||||
@@ -275,6 +279,7 @@ extension IncludedTests {
|
||||
// to regenerate.
|
||||
static let __allTests__IncludedTests = [
|
||||
("test_appending", test_appending),
|
||||
("test_ComboSparseAndFullIncludeTypes", test_ComboSparseAndFullIncludeTypes),
|
||||
("test_EightDifferentIncludes", test_EightDifferentIncludes),
|
||||
("test_EightDifferentIncludes_encode", test_EightDifferentIncludes_encode),
|
||||
("test_FiveDifferentIncludes", test_FiveDifferentIncludes),
|
||||
@@ -285,6 +290,7 @@ extension IncludedTests {
|
||||
("test_NineDifferentIncludes_encode", test_NineDifferentIncludes_encode),
|
||||
("test_OneInclude", test_OneInclude),
|
||||
("test_OneInclude_encode", test_OneInclude_encode),
|
||||
("test_OneSparseIncludeType", test_OneSparseIncludeType),
|
||||
("test_SevenDifferentIncludes", test_SevenDifferentIncludes),
|
||||
("test_SevenDifferentIncludes_encode", test_SevenDifferentIncludes_encode),
|
||||
("test_SixDifferentIncludes", test_SixDifferentIncludes),
|
||||
@@ -295,6 +301,7 @@ extension IncludedTests {
|
||||
("test_TwoDifferentIncludes_encode", test_TwoDifferentIncludes_encode),
|
||||
("test_TwoSameIncludes", test_TwoSameIncludes),
|
||||
("test_TwoSameIncludes_encode", test_TwoSameIncludes_encode),
|
||||
("test_TwoSparseIncludeTypes", test_TwoSparseIncludeTypes),
|
||||
("test_zeroIncludes", test_zeroIncludes),
|
||||
("test_zeroIncludes_encode", test_zeroIncludes_encode),
|
||||
("test_zeroIncludes_init", test_zeroIncludes_init),
|
||||
|
||||
Reference in New Issue
Block a user