콘텐츠로 건너뛰기
Home » JSON파일을 읽기 – Objective-C

JSON파일을 읽기 – Objective-C

Foundation에는 객체를 JSON 형식으로 직렬화하는 도구인 NSJSONSerialization를 제공한다. 이를 사용하면 객체 그래프를 JSON으로 변환하거나 반대로 JSON으로부터 객체 데이터를 재구성하여 사용할 수 있다. JSON 파일은 일반적인 텍스트 편집기로 열어볼 수 있는 텍스트 파일이지만, NSJSONSerialization은 파일을 읽어들인 바이트스트림을 객체로 변환한다. 따라서 파일은 NSData 형식으로 읽어들인 후에 사용하면 된다.

다음 예는 JSON 파일의 경로 문자열을 사용해 해당 위치의 파일을 읽어 사전으로 만드는 예를 보여준다. 주의할 것은 JSON 포맷은 기본적으로 키-값 쌍의 형태로 데이터를 맵핑하지만, 1차 레벨에서는 배열 형식의 객체일 수 있다. 따라서 JSON 파일을 읽은 결과는 사전일수도 있고 배열일 수도 있다. 여기서는 사전 형식의 JSON을 읽었다고 가정한다.

#import <Foundation/Foundation.h>
// Read JSON File to Dictionary
NSDictionary * JSONFromFilePath(NSString * path)
{
    // path 문자열을 URL로 변환하고, 해당 URL에서 데이터를 읽어온다.
    NSURL *url = [NSURL fileURLWithPath:path];
    NSData *data = [NSData dataWithContentsOfURL:url];
    // 파일데이터로부터 JSON을 디코딩하여 사전을 생성
    NSError *error = nil;
    id dict = [NSJSONSerializatioin
       JSONObjectWithData:data
                  options:NSJSONReadingMutableContainers
                    error:&error];
    // 실패했다면 error 값이 nil이 아니게 된다.
    if(error != nil) {
        NSLog(@"Error: %@", [error localizedDescription]);
        return nil;
    }
    return (NSDictionary<NSString*, id> *)dict;
}

사전 사용하기

다음 코드는 위 코드를 활용해서 두 개의 JSON 파일을 각각 사전으로 만들고, 두 사전을 거쳐 초성 자모값을 낱자 자모로 변환하는 맵을 생성한다. 각각의 JSON 파일 정보는 문자열-문자열로 키-값쌍이 이루어진다. 현재 Objective-C 에서는 제네릭한 타입에 대해서 타입 조건을 지정하는 게 가능하다.

NSDictionary<NSString*, NSString*> * GetJamoConverter() {
    // 빈 가변 딕셔너리 생성
    NSMutableDictionary<NSString*, NSString*> * dict =
        [NSMutableDictionary dictionary];
    // 자모코드 -> 자모이름의 사전을 JSON으로부터 생성
    NSURL *root = [NSURL fileURLWithPath:@"/usr/local/var/hangul"];
    // Objective-C 2.0에서는 선언한 모든 포인터는 nil로 초기화된다.
    NSError *error = nil;
    // URL로부터 데이터를 얻고, 이를 디코딩한다.
    NSURL *jamo_url1 = [root urlByAppendingPathComponent:@"jamo.json"];
    NSData *data = [NSData dataWithContentsOfURL:jamo_url1];
    NSDictionary *jamo1 = [NSJSONSerialization
        JSONObjectWithData:data
                   options:NSJSONReadingMutableContainers
                     error:&error];
    // 실패한 경우 처리
    if(error != nil) {
        NSLog(@"Error for loading jamo.json.");
        return nil;
    }
    // compatible_jamo.json 파일을 같은 방식으로 처리한다.
    NSURL *jamo_url2 = [root urlByAppendingPathComponent:@"compatible_jamo.json"];
    data = [NSData dataWithContentsOfURL:jamo_url2];
    error = nil;
    NSDictionary<NSString*, NSString*> * jamo2 = [NSJSONSerialization
        JSONObjectWithData:data
                   options:NSJSONReadingMutableContainers
                     error:&error];
    if(error != nil) {
        NSLog(@"Error for loading compatible_jamo.json.");
        return nil;
    }
    // 모든 자모에 대해서 공백으로 구분한 마지막 단어(기역, 니은....)를 키로
    // 자모낱자 테이블에서 코드값을 찾는다.
    for(NSString* key in jamo1) {
        NSString *value = (NSString*)[jamo1 objectForKey:key];
        NSString *name = [[(NSString*)key componentsSeparatedByString:@" "] lastObject];
        if(jamo2[name] != nil) {
            [dict setObject:jamo2[name] forKey:value];
        }
    }
    return dict;
}