swift 5.1 JSon 전환 의 Codable

7699 단어 swiftCodablejson
개발 자 에 게 는 백 스테이지 데 이 터 를 받 아들 이 고 자신의 데이터 모델 로 전환 하 는 것 이 흔 하 다.그러나 애플 개발 자로 서 직접 전환 할 수 있 는 좋 은 도구 가 없고 제3자 와 의 개발 라 이브 러 리 를 빌려 야 한다.그러면 비교적 쓰기 좋 은 것 은 YYModel, MJExtension 이다.물론 다른 창고 도 있 습 니 다.그러나 문제 가 있 습 니 다. 제3자 라 이브 러 리 에 너무 많이 사용 하면 우리 개발 자 에 게 좋 은 일이 아 닙 니 다.간단하게 분석 해 보면 장점: 기능 이 강하 고 사용 이 편리 하 며 개발 효율 을 향상 시 키 며 비교적 안전 하고 bug 가 나타 날 확률 이 적다.단점: 제3자 (주로 버 전) 에 제한 을 받 습 니 다. bug 가 있 으 면 수정 하기 쉽 지 않 고 심지어 공식 적 으로 수정 할 수 밖 에 없 으 며 개발 가방 을 확대 할 수 있 습 니 다. 너무 많이 사용 하면 컴 파일 속도 가 매우 느 리 고 실제 사용 하 는 기능 이 적 습 니 다.상기 선택 을 바탕 으로 제3자 가 스스로 고려 하지 않도록 합 니 다. 우리 의 이 글 은 여기 서 토론 하지 않 습 니 다. swift 에 있어 서 우리 의 이 글 은 주로 공식 적 인 Codable 을 어떻게 사용 하여 자신의 모델 로 전환 하 는 지 에 대해 이야기 합 니 다.본론 으로 들 어가 보 겠 습 니 다.
swift 는 Codable 인 코딩 과 디 코딩 기능 을 도입 했다. 쉽게 말 하면 json 을 자신 이 만 들 고 Codable 프로 토 콜 을 따 르 는 데이터 모델 로 전환 하 는 것 을 지원 하 는 것 이다. 클래스 일 수도 있 고 구조 체 struct 일 수도 있 으 며 구조 체 에 있어 이것 은 제3자 에 게 없 는 기능 이다.애플 은 구조 체 를 사용 하 는 것 을 공식 적 으로 추천 하 며 편리 하고 안전 하 며 메모리 사용량 이 적 으 며 메모리 방출 문 제 를 걱정 하지 않 아 도 좋 은 점 이 많다.struct 에 대해 서 말씀 드 리 겠 습 니 다.
우선 제 이 슨 데 이 터 를 만 듭 니 다:
{
    "name": "  ",
    "age": 20,
    "birthday": "1990-06",
    "location": "  ",
    "job": "  "
}

그리고 우 리 는 구조 체 모델 을 만들어 서 이 데 이 터 를 받 습 니 다.
struct UserModel: Codable {
    var name = "";
    var age = 0;
    var birthday = "";
    var location = "";
    var job = "";
}

이 구조 체 모델 은 반드시 Codable 프로 토 콜 을 실현 해 야 한 다 는 것 을 설명 한다.
그리고 우 리 는 decode 디 코딩 을 하 러 간다.
let dict = """
{
    "name": "  ",
    "age": 20,
    "birthday": "1990-06",
    "location": "  ",
    "job": "  "
}
"""
let decode = JSONDecoder();
if let data = dict.data(using: .utf8) {
    let item = try? decode.decode(UserModel.self, from: data);
    print("item: \(item)");
}

인쇄 와 함께 우 리 는 struct 의 각 값 을 정상적으로 출력 할 수 있 고 사용 하기 가 이렇게 간단 하 다 는 것 을 알 게 되 었 다.
2. 복잡 한 제 이 슨 에 대해 서도 우 리 는 해석 할 수 있다.다음 제 이 슨
{
        "name": "  ",
        "age": 20,
        "birthday": "1990-06",
        "location": "  ",
        "job": "  ",
        "students": [
            {
                "name": "  ",
                "age": 12,
                "id": 1234,
                "sex": " "
            },
            {
                "name": "  ",
                "age": 11,
                "id": 1235,
                "sex": " "
            },
            {
                "name": "  ",
                "age": 14,
                "id": 1237,
                "sex": " "
            }
        ]
    }

위 에 이것 은 비교적 복잡 한 것 입 니 다. 한 대상 은 배열 을 포함 하고 배열 안에 대상 이 있 습 니 다. 그러면 이 struct 모델 에 대해 우 리 는 이렇게 만 들 수 있 습 니 다.
struct UserModel: Codable {
    var name = "";
    var age = 0;
    var birthday = "";
    var location = "";
    var job = "";
    var students: [StudentsModel]!
}

struct StudentsModel: Codable {
    var name = "";
    var age = 0;
    var id = 0;
    var sex = "";
}

위 에 있 는 그 방법 을 사용 하면 students 가 인쇄 한 것 이 배열 이라는 것 을 볼 수 있 습 니 다.
그러나 가끔 은 상황 이 우리 가 상상 하 는 것 처럼 완벽 하지 않다. 특히 명명 규칙 에 있어 배경 에 하강 봉 이 있 는 명명 방식 이 나타 날 수 있다. 예 를 들 어 studentname 등 형식 입 니 다. swift 는 보통 낙타 봉 이 라 고 명명 되 어 있 습 니 다. 예 를 들 어 student Name 은 하나의 문 제 를 가 져 왔 습 니 다. 이 두 가지 표 시 는 일치 하지 않 습 니 다. 그러면 우 리 는 이 문 제 를 어떻게 해결 합 니까? 예 를 들 어 우 리 는 다음 과 같은 json 데이터 가 있 습 니 다.
{
    "name": "  ",
    "phone_number": 18467898765,
    "pic_url": "  "
}

이 럴 때 나 는 수 동 으로 속성 과 값 을 대응 해 야 한다.
struct UserModel: Codable {
    var name = "";
    var phoneNumber = 0;
    var picURL = "";
    
    enum UserKeys: String, CodingKey {
        case phoneNumber = "phone_number"
        case picURL = "pic_url"
        case name = "name"
    }
    
    init(from decoder: Decoder) throws{
        let value = try? decoder.container(keyedBy: UserKeys.self);
        
        phoneNumber = (try? value?.decode(Int.self, forKey: .phoneNumber)) ?? 0;
        picURL = (try? value?.decode(String.self, forKey: .picURL)) ?? "";
        name = (try? value?.decode(String.self, forKey: .name)) ?? "";
        
    }
}

위 에서 도 알 수 있 듯 이 키 와 값 의 유형 이 다 를 때 우 리 는 전환 할 수 있다.
swift 의 Codable 은 매우 간단 하고 강력 합 니 다. 만약 에 우리 가 실제 개발 할 때 백 스테이지 에서 돌아 온 데이터 가 완전 하지 않 으 면 그 값 이 없 으 면 돌아 오지 않 을 수도 있 습 니 다. 이때 우리 위의 문제 가 드 러 났 습 니 다.구체 적 으로 무슨 잘못 일 까요?우 리 는 데이터 json 의 name 을 제거 하고 다음 과 같은 형식 으로 바 꾸 었 다.
  :

{
    "age": 12,
    "birthday": "2000-01"
}

  :

struct UserModel: Codable {
    var name = "";
    var age = 0;
    var birthday = ""; 
}

테스트 방법 도 우리 가 바 꿔 보 자.
let decode = JSONDecoder();
    if let data = stringValue.data(using: .utf8) {
        do {
            let item = try decode.decode(UserModel.self, from: data);
            print("item: \(item)");
        } catch  {
            print("error =\(error)");
        }
        
    }

다음 오류 정 보 를 인쇄 합 니 다:
error =keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"name\", intValue: nil) (\"name\").", underlyingError: nil))

바로 우리 가 정의 하 는 name 은 반드시 있어 야 하지만 배경 이 돌아 오지 않 아서 오류 가 발생 했 습 니 다. 이 럴 때 우 리 는 선택 가능 한 유형 으로 정의 해 야 합 니 다. 다음 과 같 습 니 다.
struct UserModel: Codable {
    var name: String?
    var age: Int?
    var birthday: String?
}

이 럴 때 안심 하고 사용 할 수 있 습 니 다. 성공 승낙 치 는 name 만 비어 있 습 니 다.
사실 우 리 는 이러한 속성의 값 을 우리 가 사용 하 는 과정 에서 일반적으로 읽 는 것 을 발견 했다. 이 의 도 를 잘 표현 하기 위해 우 리 는 일반적으로 다음 과 같이 정의 하여 데이터 의 안전 을 확보 했다.
struct UserModel: Codable {
    let name: String?
    let age: Int?
    let birthday: String?
}

이 Codable 기능 을 더 잘 사용 하기 위해 서 는 JSONdecoder 에 확장 자 를 추가 할 수 있 습 니 다. 문 제 는 다음 과 같 습 니 다.
 
extension JSONDecoder {
    class func jsonDecoder(_ type: T.Type,from data: Data?) -> T? {
        guard let data = data else {
            return nil;
        }
        let json = JSONDecoder();
        var jsonItem: T? = nil;
        do {
            jsonItem = try json.decode(type, from: data)
        } catch {
            printObject("data convert json error: \(error)");
        }
        
        return jsonItem;
    }
    class func jsonDecoder(_ type: T.Type,fromAny data: Any?) -> T? {
        if let data = data as? Data {
            return jsonDecoder(type, from: data);
        }
        guard let data = data else {
            return nil;
        }
        if let stringValue = data as? String {
            return jsonDecoder(type, from: stringValue.data(using: .utf8));
        }
        let jsonData = try? JSONSerialization.data(withJSONObject: data, options: .prettyPrinted);
        return jsonDecoder(type, from: jsonData);
    }
}

이렇게 사용 하면 많이 편리 해진 다.자, Codable 의 사용 에 대해 이렇게 많이 말 했 습 니 다. 그리고 인 코딩 도 똑 같 습 니 다. 스스로 탐색 할 수 있 습 니 다.
아니면 그 옛말: 공부 하 는 길에 노력 하 는 사람 이 부족 하지 않다.점점

좋은 웹페이지 즐겨찾기