부트캠프/본캠프

[내일배움캠프_2025JUL16] Console 활용, [JsonConstructor]

Young_A 2025. 7. 16. 21:01

목차

    Console 활용, [JsonConstructor]

     

     

    벌써 수요일이군... 시간 참 빠르다.


    Console 활용

    Console.OutputEncoding = Encoding.UTF8;
    Console.WriteLine(new string('=', Console.WindowWidth));

     

    어제 TIL에 올렸어야 했는데 깜빡했다!

     

    늘 수동으로 ============================= 을 찍었는데 Console.WindowWidth로 콘솔 가로폭에 맞춰서 찍을 수 있다.

     

    또한 특수문자를 출력하려면, Encoding 출력을 UTF8로 설정해주어야함.


    [JsonConstructor]

    이전 개인 과제와, 현재 팀 과제의 프로퍼티 설정이 조금 다르다.

    하나로 맞추고 싶었고, 팀원들이 공통적으로 이해하기 쉽다고 생각하는 방법으로 읽기 전용 프로퍼티를 다음과 같이 만들었다.

    public JobType JobType { get; private set; }
    public Inventory Inventory { get; private set; }
    public uint NumOfStones { get; private set; }

     

    그러다보니 [JsonProperty]로도 역직렬화가 불가능해졌다.

    [JsonProperty]는 private 혹은 protected 프로퍼티만 직렬화, 역직렬화가 가능하게 하고,

    public 필드의 {get, private set}의 경우에는 직렬화는 잘 되지만, 역직렬화가 불가능하다.

    (이전에 레딧에서 찾은 해결법에는 private set을 역직렬화할 수 있다고 했던 것 같은데 실제로 해보니까 안되서 당황;;)

     

    그래서!

    [JsonProperty] 설정을 사용하는 private 필드를 전부 만들고,

    [JsonIgnore] 설정을 public 프로퍼티에 전부 적용을 했.었.다!

    하지만 커밋할때 지옥의 충돌 해결을 해야할 것 같아서... 더 좋은 방법을 찾아봤다!

     

    역직렬화 전용 생성자만 만들어주면 되는 [JsonConstructor]를 써봤다.

    필요한 모든 필드를 생성자 파라미터로 받아서 초기화하면 된다.

    다만, 내부에 내부에 복합 개체 (가벼운 참조 하는 녀석들)은 Clone() 메서드를 통해 복사 처리하는 것이 좋다.

     

    [JsonConstructor]가 지정된 생성자는 역직렬화시 기본 생성자보다 무조건 우선적으로 호출된다.

    [JsonConstructor]
    public Player(
        uint id,
        string name,
        uint hp,
    /* 중략 */
        Inventory inventory,
        uint gold,
        uint exp
    ) : base(name)
    {
        Console.WriteLine("Player 역직렬화 생성자");
        this.Id = id;
        this.Name = name;
        this.HP = hp;
    /* 중략 */
        this.Inventory.Clone(inventory);
        this.Gold = gold;
        this.Exp = exp;
    }

     

     

    참고로, [JsonProperty] 없이도 역직렬화하려면 생성자 파라미터 이름이 Json 키 이름과 정확히 일치해야한다.

    Newtonsoft.Json은 대소문자 구분을 하지 않는다.

    또한 key 값을 사용하기 때문에 속성의 순서 또한 무시한다.

     

    하지만 불안하다면 [JsonProperty]로 key 값을 수동으로 설정하는 것도 좋은 방법일 것 같다.

    이 경우에는 괜히 또 무언가 건드렸다가 에러가 날까봐 그냥 잘 되는 상태로 두었다.

    추상 클래스를 상속 받는 개체에 [JsonConstructor]를 쓰려면?

    이미 위에 올린 코드처럼, 부모 클래스의 생성자를 base로 명시적으로 호출하는 경우 부모 추상 클래스에서도 [JsonConstructor]를 설정해주어야 한다. (지금 보니.. 명시적 호출 빼고 추상클래스에 [JsonConstructor] 설정 안해도 됬을 듯)

    [JsonConstructor]
    public Character(
        uint id,
        string name,
        uint hP,
        uint mP,
        uint attack,
        uint defense)
    {
        this.Id = id;
        this.Name = name;
        this.HP = hP;
        this.MP = mP;
        this.Attack = attack;
        this.Defense = defense;
    }

     


    저장에 에러가 났다면? 체크리스트

    Json을 쓰면서 에러가 날 때마다 우왕좌왕 이곳저곳을 건드리느라 시간이 많이 소모되는 것을 느꼈다.

    이번 문제 해결들을 하면서 Json 문제가 생겼을 때 순서대로 따라가는 체크리스트를 정리했다.

    1. 저장 경로와 파일 이름
      1. 저장하는 경로가 올바른지, 파일 생성 여부를 통해 확인.
      2. 되도록 path는 string으로 저장하여 하드코딩하는 것을 피하는 것이 좋다.
    2. 저장 직전 데이터 준비
      1. 데이터를 담은 객체가 제대로 준비 되어있는지 확인.
      2. 해당 객체의 변화를 디버깅으로 확인하거나 Console.WriteLine으로 체크.
    3. 직렬화 설정
      1. Json 직렬화 설정이 적절한지 확인한다.
      2. [JsonProperty]와 같은 설정들 & 커스텀 컨버터가 제대로 되어있는지.
      3. 생성된 파일을 열어보고 내용을 비교하여 확인할 수 있다.
    4. 불러오기 시 파일 존재 여부
      1. 존재하지 않는 파일일 경우 예외 처리 필요.
    5. 불러온 데이터 역직렬화
      1. Json 에서 객체로 변환이 제대로 되는지 확인.
      2. 역직렬화 된 객체 내부 필드 (오브젝트 들)은 null로 불러와지진 않는지 확인
      3. 해당 객체의 변화를 디버깅으로 확인하거나 Console.WriteLine으로 체크.
      4. 역직렬화된 객체에서 다른 객체나 리스트 등의 참조가 잘 연결되었는지 확인한다.

    일단 내가 직접 경험 해본 경우들 + 내 예상들로만 정리된 것이라 다른 에러가 발생할 수도 있지만,

    이 전에 겪어봤던 문제들은 빠르게 체크할 수 있을 것 같다.


    느낀점

    하... json.. 진짜 싫다...... 그치만 제대로 작동하면 그만큼 짜릿한게 없다.

    Unity Json 활용은 더 날 것이라고 들었는데... newtonsoft야 unity json도 개발해주지 않겠니? (찾아보니 plugin으로 사용한다고함)


    내일 학습 할 것은 무엇인지

    오늘 세이브 로드 데이터 때문에 던전 구현을 거의 하지 못했다.

    => 금방 구현했다!

    코드리뷰를 하지 못했는데... 내일 스크럼... 어쩌지...