사전 (번역을위한 완벽한 데이터 구조)을 확장하고 어떤 종류의 번역이 수행 될지 알려주는 마커를 추가했습니다.
internal class Translation : Dictionary<string, string>
{
public string Name { get; set; }
}
그러나 객체를 직렬화하면 출력 문자열에서 키-값 쌍만 가져옵니다. 이름이 표시되지 않습니다. 나는 마이크로 소프트 삼촌의 선물 가방, 즉 System.Text.Json 의 물건을 사용하고 싶었 기 때문에 다음을 수행한다.
string output = JsonSerializer.Serialize(source);
내 의심은 사용자 지정 직렬 변환기를 구현해야한다는 것입니다.하지만이 간단한 경우에는 너무 복잡합니다. 내 경험에 따르면 도구에 번들로 제공되는 깔끔하고 부드러운 접근 방식 (내가 알지 못하는)이 있습니다.
어떻게하나요? 또는 원활하게 가능하지 않은 경우 왜 복잡한 문제입니까 (내가 이해하지 못하는 것 같음)?
아래 양식에 JSON이 필요했습니다.
{
"name": "donkey",
"key1": "value1",
"key2": "value2",
"key3": "value3",
}
물론 키 는 name 이고 값 은 donkey 인 항목을 사전에 추가하여 해결할 수 있습니다 . 그러나 그 실용적인 해결책은 내 대체물로 저장하는 것을 선호합니다. 지금은 여유 시간이 있고 구조를 가지고 놀아보고 싶습니다. 또한 이름 이 문자열 대신 int 가 되거나 타임 스탬프 등을 설명하는 더 복잡한 구조 가 될 수 있다고 상상할 수 있습니다 . 그것은 사전의 계약을 완전히 깨뜨릴 것입니다 (문자열 대 문자열 매핑).
이것은 의도 설계 것 같다 - Newtonsoft와 같은를 JavaScriptSerializer
하고 DataContractJsonSerializer
, 사전 키와 값은 일반 속성,하지 직렬화된다.
확장의 대안으로 Dictionary<TKey, TValue>
컨테이너 클래스에서 사전을 캡슐화하고 사전을 다음으로 표시하여 원하는 JSON을 얻을 수 있습니다 JsonExtensionDataAttribute
.
internal class Translation
{
public string Name { get; set; }
[JsonExtensionData]
public Dictionary<string, object> Data { get; set; } = new Dictionary<string, object>();
}
그리고 다음과 같이 직렬화합니다.
var translation = new Translation
{
Name = "donkey",
Data =
{
{"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"},
},
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
// Other options as required
WriteIndented = true,
};
var json = JsonSerializer.Serialize(translation, options);
문서 에서이 제한 사항을 확인하십시오.
사전의 TKey 값은 String 이고 TValue는 JsonElement 또는 Object 여야합니다 .
(제쳐두고, 유사한 접근 방식이 자체 .NET JsonExtensionDataAttribute
라이브러리 가있는 Newtonsoft에서 작동 합니다. 두 라이브러리를 모두 사용하는 경우 속성을 혼동하지 않도록하십시오.)
데모 바이올린 # 1 여기 .
데이터 모델에 대한 이러한 수정이 편리하지 않은 JsonConverter<Translation>
경우 위의 모델과 같이 DTO를 (비) 직렬화 한 다음 최종 모델에서 DTO를 매핑 하는 사용자 지정 을 도입 할 수 있습니다 .
internal class Translation : Dictionary<string, string>
{
public string Name { get; set; }
}
internal class TranslationConverter : JsonConverter<Translation>
{
internal class TranslationDTO
{
public string Name { get; set; }
[JsonExtensionData]
public Dictionary<string, object> Data { get; set; }
}
public override Translation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dto = JsonSerializer.Deserialize<TranslationDTO>(ref reader, options);
if (dto == null)
return null;
var translation = new Translation { Name = dto.Name };
foreach (var p in dto.Data)
translation.Add(p.Key, p.Value?.ToString());
return translation;
}
public override void Write(Utf8JsonWriter writer, Translation value, JsonSerializerOptions options)
{
var dto = new TranslationDTO { Name = value.Name, Data = value.ToDictionary(p => p.Key, p => (object)p.Value) };
JsonSerializer.Serialize(writer, dto, options);
}
}
그리고 다음과 같이 직렬화합니다.
var translation = new Translation
{
Name = "donkey",
["key1"] = "value2",
["key2"] = "value2",
["key3"] = "value3",
};
var options = new JsonSerializerOptions
{
Converters = { new TranslationConverter() },
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
// Other options as required
WriteIndented = true,
};
var json = JsonSerializer.Serialize(translation, options);
내가 직접 일하는 DTO 오히려보다 (드) 직렬화가 간단하게 찾을 수 Utf8JsonReader
와 Utf8JsonWriter
에지의 경우와 같은 및 명명 정책을 자동으로 처리하세요. 성능이 중요한 경우에만 독자 및 작가와 직접 협력합니다.
두 방법 모두 JSON 에서 모델에 JsonNamingPolicy.CamelCase
바인딩 "name"
하는 데 필요합니다 Name
.
데모 바이올린 # 2 여기 .
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다