다음과 같이 구성된 Web Api 프로젝트가 있습니다.
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
그러나 사전 키 대소 문자를 변경하지 않고 유지하고 싶습니다. Newtonsoft.Json
직렬화 중에 대 / 소문자를 변경하지 않고 유지하기를 원한다는 것을 나타 내기 위해 클래스에 사용할 수 있는 속성이 있습니까?
public class SomeViewModel
{
public Dictionary<string, string> Data { get; set; }
}
답변
이를 수행하는 속성은 없지만 리졸버를 사용자 정의하여 수행 할 수 있습니다.
이미 CamelCasePropertyNamesContractResolver
. 여기에서 새 리졸버 클래스를 파생하고 CreateDictionaryContract()
메서드를 재정의 DictionaryKeyResolver
하면 키 이름을 변경하지 않는 대체 함수를 제공 할 수 있습니다 .
다음은 필요한 코드입니다.
class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
{
protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
{
JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);
contract.DictionaryKeyResolver = propertyName => propertyName;
return contract;
}
}
데모:
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo
{
AnIntegerProperty = 42,
HTMLString = "<html></html>",
Dictionary = new Dictionary<string, string>
{
{ "WHIZbang", "1" },
{ "FOO", "2" },
{ "Bar", "3" },
}
};
JsonSerializerSettings settings = new JsonSerializerSettings
{
ContractResolver = new CamelCaseExceptDictionaryKeysResolver(),
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(foo, settings);
Console.WriteLine(json);
}
}
class Foo
{
public int AnIntegerProperty { get; set; }
public string HTMLString { get; set; }
public Dictionary<string, string> Dictionary { get; set; }
}
다음은 위의 출력입니다. 모든 클래스 속성 이름은 카멜 케이스이지만 사전 키는 원래 케이스를 유지합니다.
{
"anIntegerProperty": 42,
"htmlString": "<html></html>",
"dictionary": {
"WHIZbang": "1",
"FOO": "2",
"Bar": "3"
}
}
답변
Json.NET 9.0.1 은 NamingStrategy
이러한 종류의 문제를 처리하기 위해 클래스 계층 구조를 도입했습니다 . 계약 확인자에서 사전 키 , 명시 적으로 지정된 속성 이름 및 확장 데이터 이름 ( 10.0.1 )이 다시 매핑 되는지 여부를 제어 할 수있는 별도의 경량 클래스로 속성 이름을 알고리즘 방식으로 다시 매핑하는 논리를 추출합니다 .
의 인스턴스 를 사용 DefaultContractResolver
하고 설정 NamingStrategy
하면 다음에서 설정 하여 CamelCaseNamingStrategy
낙타 케이스 속성 이름과 수정되지 않은 사전 키로 JSON을 생성 할 수 있습니다 JsonSerializerSettings.ContractResolver
.
var resolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = false,
OverrideSpecifiedNames = true
}
};
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver;
메모:
-
의 현재 구현은
CamelCasePropertyNamesContractResolver
또한 명시 적으로 지정된 속성 이름 (예 : 설정된 속성 이름)을 가진 .Net 구성원JsonPropertyAttribute.PropertyName
의 이름을 다시 매핑해야한다고 지정합니다.public CamelCasePropertyNamesContractResolver() { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; }
위의 내용
resolver
은이 동작을 유지합니다. 원하지 않는 경우을 설정하십시오OverrideSpecifiedNames = false
. -
Json.NET에는 다음과 같은 몇 가지 기본 제공 이름 지정 전략이 있습니다.
CamelCaseNamingStrategy
. 이전에 .NET에 포함 된 이름 다시 매핑 논리를 포함하는 낙타 케이스 명명 전략입니다CamelCasePropertyNamesContractResolver
.SnakeCaseNamingStrategy
. 뱀 케이스 명명 전략.DefaultNamingStrategy
. 기본 명명 전략입니다. 속성 이름과 사전 키는 변경되지 않습니다.
또는 추상 기본 클래스에서 상속하여 직접 만들 수 있습니다
NamingStrategy
. -
그것은 수정하는 것도 가능하지만
NamingStrategy
의 인스턴스를CamelCasePropertyNamesContractResolver
, 후자 이후, 전 세계적으로 각 유형의 모든 인스턴스에서 공유 계약 정보 응용 프로그램의 여러 인스턴스를 사용하려고하면,이 예기치 않은 부작용을 초래할 수 있습니다CamelCasePropertyNamesContractResolver
. 에는 이러한 문제가DefaultContractResolver
없으므로 케이싱 논리의 사용자 정의가 필요할 때 사용하는 것이 더 안전합니다.
답변
아주 좋은 대답입니다. 그러나 왜 그냥 무시하지 ResolveDictionaryKey
않습니까?
class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
{
#region Overrides of DefaultContractResolver
protected override string ResolveDictionaryKey(string dictionaryKey)
{
return dictionaryKey;
}
#endregion
}
답변
선택한 대답은 완벽하지만 이것을 입력 할 때까지 DictionaryKeyResolver가 더 이상 존재하지 않기 때문에 계약 해결 프로그램이 이와 같이 변경되어야한다고 생각합니다. 🙂
public class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
{
protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
{
JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);
contract.PropertyNameResolver = propertyName => propertyName;
return contract;
}
}
답변
