PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Sunday, July 24, 2022

[FIXED] How to deal with this JSON?

 July 24, 2022     json, swift     No comments   

Issue

I have this JSON coming from server:

{
  "models": [
    {
      "code": "RPX",
      "name": "Tank",
      "color": null,
      "alias": [
        "tank"
      ],
      "plantCode": "FR",
      "countryName": "France",
      "plantAlias": null,
      "plantGroup": "5",
      "matrix": [
        {
          "size": "BIG",
          "union": null
        }
      ],
      "imageURL": "https://example.com/tank.jpg"
    }
  ]
}

from this JSON I have built this model:

import Foundation

// MARK: - Welcome
struct ModelDecode: Codable {
    let models: [Model]?
}

// MARK: - Model
struct Model: Codable {
    let code, name: String?
    let color: JSONNull?
    let alias: [String]?
    let plantCode, countryName: String?
    let plantAlias: JSONNull?
    let plantGroup: String?
    let matrix: [Matrix]?
    let imageURL: String?
}

// MARK: - Matrix
struct Matrix: Codable {
    let size: String?
    let union: JSONNull?
}

// MARK: - Encode/decode helpers

class JSONNull: Codable, Hashable {

    public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
        return true
    }

    public var hashValue: Int {
        return 0
    }

    public func hash(into hasher: inout Hasher) {
        // No-op
    }

    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}

Then I have this to decode the JSON:

final class ListOfTanks:NSObject, URLSessionDelegate {
  
  private let session: URLSession = NetworkService.shared.getSession()
  private let decoder = JSONDecoder()
  private let encoder = JSONEncoder()
  
  static let shared = ListOfTanks()
  
  static func serverURL() -> URL? {
   let getServerHost = "https://example.com/request"
   let getServerPath = "/getTanks"
    
    var components = URLComponents()
    components.scheme = "https"
    components.host = getServerHost
    components.path = getServerPath
    guard let url = components.url else { return nil }
    return url
  }
  
  
  static func getRequest() -> URLRequest? {
    guard let url = ListOfTanks.serverURL()
    else { return nil }
    
    var request: URLRequest = URLRequest(url: url)
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("service", forHTTPHeaderField: "iPad")
    request.httpMethod = "GET"
    return request
  }
  
  func getStations(completion:callback<ModelDecode>?) {
        
    guard let request = ListOfTanks.getRequest() else {
      completion?(.failure("Failed to build request"))
      return }
    
    let session: URLSession = URLSession(configuration: URLSessionConfiguration.default,
                                         delegate: self,
                                         delegateQueue: OperationQueue())
    
    let task = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
      
      guard let data = data else {
        completion?(.failure("Error"))
        return
      }
      
      do {
        let result = try self.decoder.decode(ModelDecode.self, from: data)
        completion?(.success(result))
      } catch (let error) {
        print(error)
        completion?(.failure("Error Parsing Error \(String(describing:error))"))
      }
  
    }
    task.resume()
    
  }
  
}

the JSON is retrieved correctly but the last try for decoding fails with:

typeMismatch(MyApp.JSONNull, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "models", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "matrix", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "union", intValue: nil)], debugDescription: "Wrong type for JSONNull", underlyingError: nil))
failure("Error Parsing Error typeMismatch(MyApp.JSONNull, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: \"models\", intValue: nil), _JSONKey(stringValue: \"Index 1\", intValue: 1), CodingKeys(stringValue: \"matrix\", intValue: nil), _JSONKey(stringValue: \"Index 1\", intValue: 1), CodingKeys(stringValue: \"union\", intValue: nil)], debugDescription: \"Wrong type for JSONNull\", underlyingError: nil))")

How do I solve that?

NOTE: I have omitted some code that I think is implicit, once the JSON is being retrieved correctly. If you need some specific code, please ask.


Solution

The first thing you should do is get rid of that JSONNull type. It´s not helping. This type will fail to decode as soon as the JSON value is something different then null. And a property that allways stays null seems kind of pointless.

Next step would be to replace the JSONNulls with their "real" type as an optional. Multiple approaches here

  • Get a better sample. As you seem to have created this structs by quicktype.io, paste a larger dataset into it. There´s a good chance this will give you the types you need.

  • Make an assumption. As all of the properties seem to be of type String it would be (kind of) safe to assume the missing ones are of the same type. Replace JSONNull with String?

  • Ask/Read. Read the docu or contact the owner/developer of the API and ask what types there are and wich one could get null.



Answered By - burnsi
Answer Checked By - Cary Denson (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing