Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSONConverter helper #380

Merged
merged 3 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions .package.resolved
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
{
"pins" : [
{
"identity" : "apollo-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apollographql/apollo-ios.git",
"state" : {
"revision" : "99dfbdb869dbba16bd09e086b2b669bfcab811ec",
"version" : "1.12.2"
}
},
{
"identity" : "cwlcatchexception",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -50,17 +41,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/stephencelis/SQLite.swift.git",
"state" : {
"revision" : "f0af5e0a2b6917ae38e3019e3456fd0fa9365864",
"version" : "0.15.1"
"revision" : "a95fc6df17d108bd99210db5e8a9bac90fe984b8",
"version" : "0.15.3"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "46989693916f56d1186bd59ac15124caef896560",
"version" : "1.3.1"
"revision" : "0fbc8848e389af3bb55c182bc19ca9d5dc2f255b",
"version" : "1.4.0"
}
},
{
Expand Down
73 changes: 73 additions & 0 deletions Tests/ApolloTests/JSONTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,77 @@ class JSONTests: XCTestCase {

XCTAssertEqual(stringFromSerialized, #"{"aWeirdNull":null}"#)
}

func testJSONConvertSelectionSetEncoding() throws {
class Hero: MockSelectionSet {
typealias Schema = MockSchemaMetadata

override class var __selections: [Selection] {[
.field("__typename", String.self),
.field("name", String?.self)
]}

var name: String? { __data["name"] }
}

let expected: JSONObject = [
"__typename": "Human",
"name": "Johnny Tsunami"
]

let converted = try JSONConverter.convert(Hero(data: expected))
XCTAssertEqual(converted, expected)
}

func testJSONConvertGraphQLResultEncoding() throws {
class MockData: MockSelectionSet {
typealias Schema = MockSchemaMetadata

override class var __selections: [Selection] {[
.field("hero", Hero?.self)
]}

var hero: Hero? { __data["hero"] }

class Hero: MockSelectionSet {
typealias Schema = MockSchemaMetadata

override class var __selections: [Selection] {[
.field("__typename", String.self),
.field("name", String?.self)
]}

var name: String? { __data["name"] }
}
}

let jsonObj: [String: AnyHashable] = [
"hero": [
"name": "Luke Skywalker",
"__typename": "Human"
]
]

let heroData = try MockData(data: jsonObj)

let result = GraphQLResult(
data: heroData,
extensions: nil,
errors: nil,
source: .server,
dependentKeys: nil
)

let expected: [String: Any] = [
"data": [
"hero": [
"name": "Luke Skywalker",
"__typename": "Human"
]
]
]

let converted = JSONConverter.convert(result)
XCTAssertEqual(converted, expected)
}
}
7 changes: 1 addition & 6 deletions apollo-ios/Sources/Apollo/GraphQLError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,6 @@ extension GraphQLError: LocalizedError {

extension GraphQLError {
func asJSONDictionary() -> [String: Any] {
var dict: [String: Any] = [:]
if let message = self["message"] { dict["message"] = message }
if let locations = self["locations"] { dict["locations"] = locations }
if let path = self["path"] { dict["path"] = path }
if let extensions = self["extensions"] { dict["extensions"] = extensions }
return dict
JSONConverter.convert(self)
}
}
17 changes: 1 addition & 16 deletions apollo-ios/Sources/Apollo/GraphQLResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,9 @@ extension GraphQLResult {
/// - Returns: A `[String: Any]` JSON dictionary representing the ``GraphQLResult``.
public func asJSONDictionary() -> [String: Any] {
var dict: [String: Any] = [:]
if let data { dict["data"] = convert(value: data.__data) }
if let data { dict["data"] = JSONConverter.convert(data) }
if let errors { dict["errors"] = errors.map { $0.asJSONDictionary() } }
if let extensions { dict["extensions"] = extensions }
return dict
}

private func convert(value: Any) -> Any {
var val: Any = value
if let value = value as? DataDict {
val = value._data
} else if let value = value as? (any CustomScalarType) {
val = value._jsonValue
}
if let dict = val as? [String: Any] {
return dict.mapValues(convert)
} else if let arr = val as? [Any] {
return arr.map(convert)
}
return val
}
}
52 changes: 52 additions & 0 deletions apollo-ios/Sources/Apollo/JSONConverter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Foundation
#if !COCOAPODS
import ApolloAPI
#endif

public enum JSONConverter {

/// Converts a ``SelectionSet`` into a basic JSON dictionary for use.
///
/// - Returns: A `[String: Any]` JSON dictionary representing the ``SelectionSet``.
public static func convert(_ selectionSet: some SelectionSet) -> [String: Any] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as you might have guessed from my PR, I'm not a fan of relying on the compiler to select the right overload, but that's my personal preference. The changes in this PR still work fine for my use case. Thanks for the help!

selectionSet.__data._data.mapValues(convert(value:))
}

static func convert(_ dataDict: DataDict) -> [String: Any] {
dataDict._data.mapValues(convert(value:))
}

/// Converts a ``GraphQLResult`` into a basic JSON dictionary for use.
///
/// - Returns: A `[String: Any]` JSON dictionary representing the ``GraphQLResult``.
public static func convert<T>(_ result: GraphQLResult<T>) -> [String: Any] {
result.asJSONDictionary()
}

/// Converts a ``GraphQLError`` into a basic JSON dictionary for use.
///
/// - Returns: A `[String: Any]` JSON dictionary representing the ``GraphQLError``.
public static func convert(_ error: GraphQLError) -> [String: Any] {
var dict: [String: Any] = [:]
if let message = error["message"] { dict["message"] = message }
if let locations = error["locations"] { dict["locations"] = locations }
if let path = error["path"] { dict["path"] = path }
if let extensions = error["extensions"] { dict["extensions"] = extensions }
return dict
}

private static func convert(value: Any) -> Any {
var val: Any = value
if let value = value as? DataDict {
val = value._data
} else if let value = value as? any CustomScalarType {
val = value._jsonValue
}
if let dict = val as? [String: Any] {
return dict.mapValues(convert)
} else if let arr = val as? [Any] {
return arr.map(convert)
}
return val
}
}
Loading