DateTime 항목을 포함한 JSON 직렬화

예를 들면


public class Master {
    public Master(string ID, string Name, DateTime Join) {
        UserID = ID;
        UserName = Name;
        Joined = Join;
        Leaved = DateTime.MinValue;
    }

    public string UserID { get; set; }

    public string UserName { get; set; }

    public DateTime Joined { get; set; }

    public DateTime Leaved { get; set; }
}

이런 클래스가 있었다고 하자.
만만에 유용해 좋은 느낌의 시스템의 일부로서 짜넣어지고 있다고 생각해.

그런데



다양한 요구 사항이 증가하고 CS간에 JSON 데이터를 교환하고 필요하다고 생각하지 않습니까?
          이 되었어요, 좋아요?

뭐, Master 클래스를 JSON 대응하면 됩니다만.
이런 식으로 ...
[DataContract]
public class Master {
    public Master() { }

    public Master(string ID, string Name, DateTime Join) {
        UserID = ID;
        UserName = Name;
        Joined = Join;
        Leaved = DateTime.MinValue;
    }

    [DataMember(Order = 0)]
    public string UserID { get; set; }

    [DataMember(Order = 1)]
    public string UserName { get; set; }

    [DataMember(Order = 2)]
    public DateTime Joined { get; set; }

    [DataMember(Order = 3)]
    public DateTime Leaved { get; set; }



    public static Master CreateInstance(string json) {
        using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Master));
            return (Master)serializer.ReadObject(stream);
        }
    }

    public string Serialize() {
        using (MemoryStream stream = new MemoryStream()) {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(this.GetType());
            serializer.WriteObject(stream, this);
            return Encoding.UTF8.GetString(stream.ToArray());
        }
    }
}

하지만 함정이



예를 들어,
    Console.WriteLine(new Master("0000", "Toraja", DateTime.Today).Serialize());

같은 느낌으로 JSON을 얻을 수 있다고 생각하지 않습니까, 보통.
하지만,



라고 화가 버립니다.

여기저기서 그런 상황이 발생하고 있는 것 같아서, 여러분 해설해 주시고 있으므로, 자세한 것은 구그라고 봐 주세요.

일단 간단하게 말하면, DateTime을 직렬화 할 때에 그 값을 UTC로 변환하겠습니다만, 그 값이 MinValue였을 경우 마이너스 9시간했을 때에 언더 플로를 일으킨다고 말하는 것 같습니다만 그럼 어떻게 하면 좋다는 느낌입니다.

그래서, 식자의 의견에 의하면, JSON의 정의에는 DateTime형은 포함되어 있지 않기 때문에, 일자를 JSON에 넣고 싶은 경우에는 캐릭터 라인으로서 취급할 수 있다!
라고 말하는 것이 정론인 것 같습니다.

어떻게 대응하는가?



아니-그래도, 만만에 쓰고 있어요.
이제 클래스 정의의 DateTime을 string 형으로 변경하면 영향 범위가 어디까지 미칠 것인가 ...

라고 일로, 생각을 반전시키는 것이 좋은 것일까, 라고.
이렇게 말하는 느낌 (주목 부분만 묶었습니다).
    [IgnoreDataMember]
    public DateTime Joined { get; set; }

    [IgnoreDataMember]
    public DateTime Leaved { get; set; }

    [DataMember(Order = 2, Name = "Joined")]
    private string StringJoined {
        get { return $"{Joined:yyyyMMddHHmmss}"; }
        set { Joined = DateTime.ParseExact(value, "yyyyMMddHHmmss", CultureInfo.CurrentCulture, DateTimeStyles.None); }
    }

    [DataMember(Order = 3, Name = "Leaved")]
    private string StringLeaved {
        get { return $"{Leaved:yyyyMMddHHmmss}"; }
        set { Joined = DateTime.ParseExact(value, "yyyyMMddHHmmss", CultureInfo.CurrentCulture, DateTimeStyles.None); }
    }

내부의 Datetime 형의 프로퍼티은 JSON 에는 나오지 않게 해, JSON 에 발행하는 측의 프로퍼티을 private의 string형으로서 신설합니다. 서서 이름을 조금 바꾸어 주면 좋은 느낌일지도…

그리고 결과는 다음과 같습니다.
{"UserID":"0000","UserName":"Toraja","Joined":"20190723000000","Leaved":"00010101000000"}

아, 혹시



그리니치보다 서쪽에있는 나라에서는 이렇게 우울한 눈에 맞지 않을 것입니다.
분명히

좋은 웹페이지 즐겨찾기