XScript 매뉴얼 · Chapter 34

JSON 객체 — JSON 문서 처리

스크립트에서 키워드 JSON 으로 접근하는 JSON 유틸. 한 프로세스에서 여러 개의 JSON 문서를 이름으로 식별하며, 각 문서를 path 표기법(/root/items/0/name) 으로 자유롭게 읽고 씁니다.

개념설명
jsonNameJSON 문서 식별자 — 사용자가 부여 ("recipe", "mes_response" 등)
path문서 내부 위치 — /key/key2/0/name (객체는 키, 배열은 인덱스)
결과 / 에러모든 호출은 내부에 결과 플래그를 남김 — GetResult / GetErrorMessage

기본 사용 흐름

// 1) 비어 있는 JSON 문서 생성
JSON.CreateJson("recipe");
 
// 2) 값 쓰기 (path 가 없으면 자동 생성)
JSON.SetValue("recipe", "/title",       "AlignRecipe");
JSON.SetValue("recipe", "/version",     2);
JSON.SetValue("recipe", "/exposure_ms", 18.5);
JSON.SetValue("recipe", "/use_filter",  true);
 
// 3) 직렬화
string text = JSON.ToJsonString("recipe");
Log(text);
// {"title":"AlignRecipe","version":2,"exposure_ms":18.5,"use_filter":true}
 
// 4) 디스크에 저장
JSON.SaveJsonFile("recipe", "D:/Recipes/align.json");
 
// 5) 더 이상 필요 없으면 제거
JSON.RemoveJson("recipe");

문서 라이프사이클

// 메모리에 로드
JSON.LoadJsonFile("mes",       "D:/Mes/inbound.json");
JSON.LoadJson    ("inline",    "{\"a\":1,\"b\":[2,3]}");
 
// 존재 확인 / 비우기 / 제거
if( JSON.Contains("mes") )      JSON.ClearJsonData("mes");
JSON.RemoveJson("mes");
JSON.RemoveAll();   // 등록된 모든 JSON 문서 제거

값 쓰기 — SetValue (오버로드 4 종)

JSON.SetValue("doc", "/name",     "Alice");      // string
JSON.SetValue("doc", "/age",      30);           // int
JSON.SetValue("doc", "/weight",   62.4);         // double
JSON.SetValue("doc", "/active",   true);         // bool
 
JSON.SetNullValue("doc", "/parent_id");          // null 명시

존재하지 않는 path 는 자동으로 만들어줍니다 — 굳이 AddObject 를 먼저 호출할 필요가 없습니다. 단, 배열 인덱스를 쓰려면 그 배열은 미리 존재해야 합니다.


값 읽기 — GetXxxValue

string n = JSON.GetStringValue("doc", "/name");                 // "Alice"
int    a = JSON.GetIntValue   ("doc", "/age");                  // 30
double w = JSON.GetDoubleValue("doc", "/weight",  -1.0);        // path 없으면 -1.0
bool   v = JSON.GetBoolValue  ("doc", "/active",  false);       // 기본값 fallback

3 번째 인자(default value) 가 있으면 — 키 누락이나 타입 불일치 시 그 값을 돌려줍니다.

path 끝 trailing 가져오기

// 어떤 경로에서 시작해 그 노드의 모든 child key 와 값을 한 문자열로
string sub = JSON.GetJsonStringByPath("doc", "/items/0");

객체 / 배열 추가

// 객체 노드 추가
JSON.AddObject("doc", "/",     "items");        // /items 가 빈 객체로
JSON.AddObject("doc", "/items", "first");       // /items/first 가 빈 객체로
 
// 배열 노드 추가
JSON.AddArray ("doc", "/",     "tags");         // /tags 가 빈 배열로
 
// 배열에 push (객체 1개 / 배열 1개)
JSON.AddObjectToArray("doc", "/items", 1);      // 빈 객체 1개 push
JSON.AddArrayToArray ("doc", "/tags",  1);      // 빈 배열 1개 push
 
// 직접 SetValue 로 인덱스 지정도 가능
JSON.SetValue("doc", "/tags/0", "auto");
JSON.SetValue("doc", "/tags/1", "vision");

배열 항목 관리

int n = JSON.GetItemCount("doc", "/tags");      // 항목 수
 
JSON.RemoveFromArray("doc", "/tags", 0);        // index 0 삭제
JSON.MoveArrayItem  ("doc", "/tags", 1, true);  // index 1 → 위로 (index 0 과 교체)
JSON.MoveArrayItem  ("doc", "/tags", 0, false); // index 0 → 아래로
JSON.ClearArray     ("doc", "/tags");           // 모두 삭제

결과 / 에러 처리

모든 호출은 내부적으로 결과 플래그를 갱신합니다.

JSON.SetValue("doc", "/x/y/z", 1);
 
if( JSON.GetResult("doc") == false )
{
    LogError($"JSON SetValue failed : {JSON.GetErrorMessage("doc")}");
    JSON.ResetResult("doc");
}

여러 호출 후 한꺼번에 검증하는 패턴이 권장됩니다.

JSON.ResetResult("doc");
JSON.SetValue("doc", "/a", 1);
JSON.SetValue("doc", "/b/c", 2);
JSON.SetValue("doc", "/b/arr/0", "x");
if( JSON.GetResult("doc") == false )
{
    ShowMessage(EB_Ok, JSON.GetErrorMessage("doc"));
    return false;
}

직렬화 / 보기 좋게

string compact = JSON.ToJsonString("doc");          // 한 줄
string pretty  = JSON.FormatJson(compact);          // 들여쓰기 추가

FormatJson 은 입력 문자열을 받아 보기 좋은 형태로 변환만 합니다 — 등록된 문서를 건드리지 않음.


자주 쓰는 패턴

레시피 저장/불러오기

FUNCTION SaveRecipe(string filePath)
{
    JSON.CreateJson("rec");
    JSON.SetValue("rec", "/exposure_ms", Data::Exposure);
    JSON.SetValue("rec", "/light_pct",   Data::Light);
    JSON.AddArray("rec", "/", "trims");
    for(i, 0, 9)
    {
        JSON.AddObjectToArray("rec", "/trims", 1);
        JSON.SetValue("rec", $"/trims/{i}/x", Data::TrimX[i]);
        JSON.SetValue("rec", $"/trims/{i}/y", Data::TrimY[i]);
    }
    JSON.SaveJsonFile("rec", filePath);
    JSON.RemoveJson("rec");
}
 
FUNCTION LoadRecipe(string filePath)
{
    if( JSON.LoadJsonFile("rec", filePath) == false )
    {
        ShowMessage(EB_Ok, $"Load failed : {JSON.GetErrorMessage("rec")}");
        return false;
    }
    Data::Exposure = JSON.GetDoubleValue("rec", "/exposure_ms", 0);
    Data::Light    = JSON.GetIntValue   ("rec", "/light_pct",   0);
 
    int n = JSON.GetItemCount("rec", "/trims");
    for(i, 0, n - 1)
    {
        Data::TrimX[i] = JSON.GetDoubleValue("rec", $"/trims/{i}/x", 0);
        Data::TrimY[i] = JSON.GetDoubleValue("rec", $"/trims/{i}/y", 0);
    }
    JSON.RemoveJson("rec");
    return true;
}

MES 응답 파싱

JSON.LoadJson("resp", responseString);
 
if( JSON.GetBoolValue("resp", "/ok", false) == false )
{
    ShowError(EB_Reset, 1, JSON.GetStringValue("resp", "/message"));
    return false;
}
int lotSeq = JSON.GetIntValue("resp", "/data/lot_seq", 0);

함수 한눈 요약

분류함수
라이프사이클CreateJson · LoadJson · LoadJsonFile · SaveJsonFile · RemoveJson · RemoveAll · ClearJsonData · Contains
결과GetResult · GetErrorMessage · ResetResult
쓰기SetValue(string/int/double/bool) · SetNullValue
읽기GetStringValue · GetIntValue · GetDoubleValue · GetBoolValue · GetJsonStringByPath
트리 구성AddObject · AddArray
배열 조작AddObjectToArray · AddArrayToArray · RemoveFromArray · ClearArray · GetItemCount · MoveArrayItem
직렬화ToJsonString · FormatJson