83.7 JSON 파일 쓰기

지금까지 JSON파일의 내용을 읽고 분석하여 값을 출력해보았습니다. 이번에는 반대로 프로그램에서 JSON 문서를 생성해보겠습니다.

다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요. 단순히 JSON 형식에 맞춰서 출력하므로 코드가 간단합니다(파일은 GitHub 저장소의 Unit 83/83.7/json/json 폴더에 들어있습니다).

json.c

#define _CRT_SECURE_NO_WARNINGS    // fopen 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>     // 파일 처리 함수가 선언된 헤더 파일

int main()
{
    // JSON 문서에 저장할 데이터
    char *title = "Inception";
    int year = 2010;
    int runtime = 148;
    char *genre = "Sci-Fi";
    char *director = "Christopher Nolan";
    char actors[5][30] = {
        "Leonardo DiCaprio",
        "Joseph Gordon-Levitt",
        "Ellen Page",
        "Tom Hardy",
        "Ken Watanabe"
    };
    double imdbRating = 8.8;

    FILE *fp = fopen("example.json", "w");    // 쓰기 모드로 파일 열기

    // JSON 문법에 맞춰서 fprintf 함수로 값 출력
    fprintf(fp, "{\n");
    fprintf(fp, "  \"Title\": \"%s\",\n", title);
    fprintf(fp, "  \"Year\": %d,\n", year);
    fprintf(fp, "  \"Runtime\": %d,\n", runtime);
    fprintf(fp, "  \"Genre\": \"%s\",\n", genre);
    fprintf(fp, "  \"Director\": \"%s\",\n", director);
    fprintf(fp, "  \"Actors\": [\n");
    fprintf(fp, "    \"%s\", \n", actors[0]);
    fprintf(fp, "    \"%s\", \n", actors[1]);
    fprintf(fp, "    \"%s\", \n", actors[2]);
    fprintf(fp, "    \"%s\", \n", actors[3]);
    fprintf(fp, "    \"%s\" \n", actors[4]);
    fprintf(fp, "  ],\n");
    fprintf(fp, "  \"imdbRating\": %.1f\n", imdbRating);
    fprintf(fp, "}\n");

    fclose(fp);    // 파일 닫기

    return 0;
}

Visual Studio에서 Ctrl+F5 키를 눌러서 프로그램을 실행하면 .c 파일이 있는 폴더에 다음과 같은 내용으로 example.json 파일이 생성됩니다.

example.json

{
  "Title": "Inception",
  "Year": 2010,
  "Runtime": 148,
  "Genre": "Sci-Fi",
  "Director": "Christopher Nolan",
  "Actors": [
    "Leonardo DiCaprio", 
    "Joseph Gordon-Levitt", 
    "Ellen Page", 
    "Tom Hardy", 
    "Ken Watanabe" 
  ],
  "imdbRating": 8.8
}

JSON 문서를 만드는 방법은 간단합니다. JSON 문법에 맞춰서 fprintf 함수로 파일에 출력만 해주면 됩니다. 여기서 주의할 점은 " " (큰따옴표)안에 "를 사용하려면 \"와 같이 앞에 \를 붙여주어야 한다는 점입니다.

지금까지 작성한 JSON 파서는 다음과 같은 한계를 가지고 있습니다.

  • 고정된 토큰 개수
  • 불 값(true, false) 파싱이 구현되지 않음
  • 숫자, 불 배열 파싱이 구현되지 않음
  • 처음부터 배열로 시작하는 문서를 지원하지 않음
  • 객체 안에 객체 또는 배열 들어가는 문법을 지원하지 않음
  • 배열 안에 객체 또는 배열이 들어가는 문법을 지원하지 않음
  • 키의 값을 가져올 때 매번 모든 토큰을 검사하는 비효율적인 구조

지원되지 않는 부분이 많죠? 구문 분석(파서) 분야는 생각보다 복잡하고 난이도가 높은 분야입니다. 그래서 구문 분석을 완벽하게 구현하고 설명하려면 책 한 권도 모자랄 정도입니다. 특히 컴퓨터공학 과목 중에서 컴파일러는 구문 분석이 큰 비중을 차지합니다.

현재 인터넷에는 C 언어로 구현된 JSON 파서가 많이 나와있습니다. 이런 상태에서 JSON을 완벽하게 처리하는 파서를 다시 구현하는 일은 바퀴의 재발명에 비유할 수 있습니다. 따라서 보통 실무에서는 기존에 구현된 JSON 파서를 가져다 쓰는 경우가 많습니다.

예제처럼 JSON 문법에 맞춰서 문서를 생성하는 방법은 상당히 초보적인 방법입니다. 다음 유닛에서는 GitHub에 있는 JSON 파서를 이용해서 JSON 문서를 파싱하고, 생성하는 방법을 알아보겠습니다.