nullable을 활성화 하여 컴파일시점에서 항상 맴버가 null이 아님을 보증하는 불변객체를 운용하고자 한다.
record Obj(object o);
이정도만 해도 코드상에서는 construct 시점 등에 null이 입력될 가능성을 없엘수가 있다.
문제는 Json 역직렬화 같은 동작을 통해 어떠한 warring이나 Exception발생 없이 런타임에서 null맴버가 주입될 가능성이 있다는것인데,
필요한 키밸류가 아예 없는경우는 선언적인 제약이 가능하나, 아예 사용자가 키값으로 null을 직접 집어넣는짓거리를 한다면, 기본값같은것도 소용이 없고 아주 순순히 null맴버가 되어버린다는 문제가 있다.
때문에 그런 경우를 직접 저항하는 코드를 작성해야만 했다.
using System;
using System.Text.Json;
using System.Diagnostics.CodeAnalysis;
using System.Text.Encodings.Web;
static object? Test<T>(string json)
{
try { return JsonSerializer.Deserialize<T>(json)?.ToString(); }
catch(Exception e) { return e.Message; }
}
static object? Tests(string json) => new
{
A = Test<A>(json),
B = Test<B>(json),
C = Test<C>(json),
D = Test<D>(json),
E = Test<E>(json),
};
Console.WriteLine(JsonSerializer.Serialize(new
{
nokey = Tests("{}"),
nullvalue = Tests("""{"o":null}"""),
}, options: new() { WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }));
record A(object o);
record B { public object o { get; init; } = new(); }
record C { public required object o { get; init; } }
record D { public object o { get; init => field = value ?? field; } = new(); }
record E { public object o { get; init => field = value ?? throw new("do not input null!"); } = new(); }
null입력을 무시하고자 한다면 D, 엄격하게 난리칠생각이라면 E 처럼 작성하면 된다.
리플렉션 Setter를 통한 값 입력에도 저항할수가 있다.
json 역직렬화 속성이나 옵션을 통하는 방법이 있을지는 모르겠으나, 기본값이 아닌이상 직관적으로 신뢰하지를 못한다.
댓글 0