Merge branch 'feature/coding' of gitlab.verizon.com:BPHV_MIPS/mvm_core into feature/coding
This commit is contained in:
commit
46c092f99c
@ -1,10 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public typealias JSONArray = [[String: Any]]
|
|
||||||
public typealias JSONObject = [String: Any]
|
|
||||||
|
|
||||||
public enum JSONError: Error {
|
|
||||||
case pathNotFound
|
|
||||||
case data(path: String)
|
|
||||||
case other(error: Error)
|
|
||||||
}
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public typealias JSONValueArray = [[String: JSONValue]]
|
|
||||||
public typealias JSONValueObject = [String: JSONValue]
|
|
||||||
|
|
||||||
public enum JSONValueError: Error {
|
|
||||||
case encode
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Optional {
|
|
||||||
func or(_ other: Optional) -> Optional {
|
|
||||||
switch self {
|
|
||||||
case .none: return other
|
|
||||||
case .some: return self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolve(with error: @autoclosure () -> Error) throws -> Wrapped {
|
|
||||||
switch self {
|
|
||||||
case .none: throw error()
|
|
||||||
case .some(let wrapped): return wrapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum JSONValue: Codable, Equatable {
|
|
||||||
case string(String)
|
|
||||||
case int(Int)
|
|
||||||
case double(Double)
|
|
||||||
case bool(Bool)
|
|
||||||
case object([String: JSONValue])
|
|
||||||
case array([JSONValue])
|
|
||||||
case null
|
|
||||||
public init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.singleValueContainer()
|
|
||||||
let value = ((try? container.decode(String.self)).map(JSONValue.string))
|
|
||||||
.or((try? container.decode(Int.self)).map(JSONValue.int))
|
|
||||||
.or((try? container.decode(Double.self)).map(JSONValue.double))
|
|
||||||
.or((try? container.decode(Bool.self)).map(JSONValue.bool))
|
|
||||||
.or((try? container.decode([String: JSONValue].self)).map(JSONValue.object))
|
|
||||||
.or((try? container.decode([JSONValue].self)).map(JSONValue.array))
|
|
||||||
|
|
||||||
self = value ?? JSONValue.null
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode<T: Decodable>() throws -> T {
|
|
||||||
let encoded = try JSONEncoder().encode(self)
|
|
||||||
return try JSONDecoder().decode(T.self, from: encoded)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
|
||||||
var container = encoder.singleValueContainer()
|
|
||||||
switch self {
|
|
||||||
case .string(let string): try container.encode(string)
|
|
||||||
case .int(let int): try container.encode(int)
|
|
||||||
case .double(let double): try container.encode(double)
|
|
||||||
case .bool(let bool): try container.encode(bool)
|
|
||||||
case .object(let object): try container.encode(object)
|
|
||||||
case .array(let array): try container.encode(array)
|
|
||||||
case .null: break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func ==(lhs: JSONValue, rhs: JSONValue) -> Bool {
|
|
||||||
let ld = try? lhs.encode()
|
|
||||||
let rd = try? lhs.encode()
|
|
||||||
return ld == rd
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONValue: ExpressibleByStringLiteral {
|
|
||||||
public init(stringLiteral value: String) {
|
|
||||||
self = .string(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONValue: ExpressibleByIntegerLiteral {
|
|
||||||
public init(integerLiteral value: Int) {
|
|
||||||
self = .int(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONValue: ExpressibleByFloatLiteral {
|
|
||||||
public init(floatLiteral value: Double) {
|
|
||||||
self = .double(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONValue: ExpressibleByBooleanLiteral {
|
|
||||||
public init(booleanLiteral value: Bool) {
|
|
||||||
self = .bool(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONValue: ExpressibleByArrayLiteral {
|
|
||||||
public init(arrayLiteral elements: JSONValue...) {
|
|
||||||
self = .array(elements)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONValue: ExpressibleByDictionaryLiteral {
|
|
||||||
public init(dictionaryLiteral elements: (String, JSONValue)...) {
|
|
||||||
self = .object([String: JSONValue](uniqueKeysWithValues: elements))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Dictionary where Key == String, Value == Any {
|
|
||||||
public func toJSONValue() throws -> [String: JSONValue] {
|
|
||||||
let data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
|
|
||||||
return try JSONDecoder().decode([String:JSONValue].self, from: data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Dictionary where Key == String, Value == JSONValue {
|
|
||||||
public func toJSONObject() throws -> JSONObject {
|
|
||||||
let encoded = try JSONEncoder().encode(self)
|
|
||||||
guard let json = try JSONSerialization.jsonObject(with: encoded, options: .mutableContainers) as? JSONObject else {
|
|
||||||
throw JSONValueError.encode
|
|
||||||
}
|
|
||||||
return json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,7 +11,7 @@ import Foundation
|
|||||||
@objcMembers public class ActionModel: Codable {
|
@objcMembers public class ActionModel: Codable {
|
||||||
public var actionType: String?
|
public var actionType: String?
|
||||||
|
|
||||||
public init(actionType: String?, pageType: String?) {
|
public init(actionType: String?) {
|
||||||
self.actionType = actionType
|
self.actionType = actionType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public protocol AnyDecoder {
|
|
||||||
func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONDecoder: AnyDecoder {}
|
|
||||||
extension PropertyListDecoder: AnyDecoder {}
|
|
||||||
|
|
||||||
extension Data {
|
|
||||||
public func decode<T: Decodable>(using decoder: AnyDecoder = JSONDecoder()) throws -> T {
|
|
||||||
return try decoder.decode(T.self, from: self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension KeyedDecodingContainerProtocol {
|
|
||||||
public func decode<T: Decodable>(forKey key: Key) throws -> T {
|
|
||||||
return try decode(T.self, forKey: key)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func decode<T: Decodable>(
|
|
||||||
forKey key: Key,
|
|
||||||
default defaultExpression: @autoclosure () -> T
|
|
||||||
) throws -> T {
|
|
||||||
return try decodeIfPresent(T.self, forKey: key) ?? defaultExpression()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Decodable {
|
|
||||||
public static func decode(fileName: String, bundle: Bundle = Bundle.main) throws -> Self {
|
|
||||||
guard let path = bundle.path(forResource: fileName, ofType: ".json") else {
|
|
||||||
throw JSONError.pathNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let jsonData = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
|
||||||
throw JSONError.data(path: path)
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
return try jsonData.decode()
|
|
||||||
} catch {
|
|
||||||
throw JSONError.other(error: error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public protocol AnyEncoder {
|
|
||||||
func encode<T: Encodable>(_ value: T) throws -> Data
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSONEncoder: AnyEncoder {}
|
|
||||||
extension PropertyListEncoder: AnyEncoder {}
|
|
||||||
|
|
||||||
extension Encodable {
|
|
||||||
public func encode(using encoder: AnyEncoder = JSONEncoder()) throws -> Data {
|
|
||||||
return try encoder.encode(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func toJSON() -> JSONObject? {
|
|
||||||
guard let data = try? encode() else { return nil }
|
|
||||||
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? JSONObject }
|
|
||||||
}
|
|
||||||
|
|
||||||
public func toJSONString() -> String? {
|
|
||||||
guard let data = try? encode(),
|
|
||||||
let string = String(data: data, encoding: .utf8) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public protocol Holdable: Codable {
|
|
||||||
static var identifier: String { get set }
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public struct HolderManager {
|
|
||||||
public enum Error: Swift.Error {
|
|
||||||
case codingKeyNotFound
|
|
||||||
case encoderError
|
|
||||||
case decoderError
|
|
||||||
case decoderErrorObjectNotPresent
|
|
||||||
case decoderErrorModelNotMapped
|
|
||||||
}
|
|
||||||
fileprivate static var types: [String: Holdable.Type] = [:]
|
|
||||||
public static func register<A: Holdable>(_ type: A.Type) {
|
|
||||||
types[A.identifier] = type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension KeyedDecodingContainer where Key : CodingKey {
|
|
||||||
public enum TypeCodingKey: String, CodingKey {
|
|
||||||
case actionType
|
|
||||||
}
|
|
||||||
|
|
||||||
//MARK: - Decode
|
|
||||||
public func decode<T>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeCodingKey) throws -> T {
|
|
||||||
guard let holdable: Holdable = try decodeIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
|
|
||||||
throw HolderManager.Error.decoderErrorObjectNotPresent
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let h = holdable as? T else {
|
|
||||||
throw HolderManager.Error.decoderError
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
public func decode(codingKey: KeyedDecodingContainer<K>.Key) throws -> ActionTypeProtocol {
|
|
||||||
return try decode(codingKey: codingKey, typeCodingKey: .actionType)
|
|
||||||
}
|
|
||||||
|
|
||||||
//MARK: - DecodeIfPresent
|
|
||||||
public func decodeIfPresent<T>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeCodingKey) throws -> T? {
|
|
||||||
|
|
||||||
//get the type
|
|
||||||
let meta = try self.nestedContainer(keyedBy: TypeCodingKey.self, forKey: codingKey)
|
|
||||||
|
|
||||||
guard let type = try meta.decodeIfPresent(String.self, forKey: typeCodingKey) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the type
|
|
||||||
guard let found = HolderManager.types[type] else {
|
|
||||||
throw HolderManager.Error.decoderErrorModelNotMapped
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the decoder for the propertyKey
|
|
||||||
let decoder = try self.superDecoder(forKey: codingKey)
|
|
||||||
|
|
||||||
//decode the type using the decoder
|
|
||||||
let holdable = try found.init(from: decoder)
|
|
||||||
|
|
||||||
guard let h = holdable as? T else {
|
|
||||||
throw HolderManager.Error.decoderError
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
public func decodeIfPresent(codingKey: KeyedDecodingContainer<K>.Key) throws -> ActionTypeProtocol? {
|
|
||||||
return try decodeIfPresent(codingKey: codingKey, typeCodingKey: .actionType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension KeyedEncodingContainer where Key : CodingKey {
|
|
||||||
|
|
||||||
public mutating func encodeIfPresent(_ value: Holdable?, forKey key: KeyedEncodingContainer<K>.Key) throws {
|
|
||||||
if let v = value {
|
|
||||||
let encoder = self.superEncoder(forKey: key)
|
|
||||||
try v.encode(to: encoder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public mutating func encode(_ value: Holdable, forKey key: KeyedEncodingContainer<K>.Key) throws {
|
|
||||||
let encoder = self.superEncoder(forKey: key)
|
|
||||||
try value.encode(to: encoder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user