사전을 직렬화 할 때 대 / 소문자 유지
다음과 같이 구성된 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 introduced the NamingStrategy
class hierarchy to handle this sort of issue. It extracts the logic for algorithmic remapping of property names from the contract resolver to a separate, lightweight class that allows for control of whether dictionary keys, explicitly specified property names, and extension data names (in 10.0.1) are remapped.
By using DefaultContractResolver
and setting NamingStrategy
to an instance of CamelCaseNamingStrategy
you can generate JSON with camel-cased property names and unmodified dictionary keys by setting it in JsonSerializerSettings.ContractResolver
:
var resolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = false,
OverrideSpecifiedNames = true
}
};
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver;
Notes:
The current implementation of
CamelCasePropertyNamesContractResolver
also specifies that .Net members with explicitly specified property names (e.g. ones whereJsonPropertyAttribute.PropertyName
has been set) should have their names remapped:public CamelCasePropertyNamesContractResolver() { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; }
The above
resolver
preserves this behavior. If you don't want this, setOverrideSpecifiedNames = false
.Json.NET has several built-in naming strategies including:
CamelCaseNamingStrategy
. A camel case naming strategy that contains the name-remapping logic formerly embedded inCamelCasePropertyNamesContractResolver
.SnakeCaseNamingStrategy
. A snake case naming strategy.DefaultNamingStrategy
. The default naming strategy. Property names and dictionary keys are unchanged.
Or, you can create your own by inheriting from the abstract base class
NamingStrategy
.While it is also possible to modify the
NamingStrategy
of an instance ofCamelCasePropertyNamesContractResolver
, since the latter shares contract information globally across all instances of each type, this can lead to unexpected side-effects if your application tries to use multiple instances ofCamelCasePropertyNamesContractResolver
. No such problem exists withDefaultContractResolver
, so it is safer to use when any customization of casing logic is required.
That is a very nice answer. But why not just override the ResolveDictionaryKey
?
class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
{
#region Overrides of DefaultContractResolver
protected override string ResolveDictionaryKey(string dictionaryKey)
{
return dictionaryKey;
}
#endregion
}
The selected answer is perfect but I guess by the time I'm typing this, the contract resolver must change to something like this because DictionaryKeyResolver doesn't exists anymore :)
public class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
{
protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
{
JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);
contract.PropertyNameResolver = propertyName => propertyName;
return contract;
}
}
참고URL : https://stackoverflow.com/questions/24143149/keep-casing-when-serializing-dictionaries
'programing' 카테고리의 다른 글
double 또는 float를 사용해야합니까? (0) | 2020.10.09 |
---|---|
Comparator를 사용하여 사용자 지정 정렬 순서를 정의하려면 어떻게합니까? (0) | 2020.10.09 |
PHP CURL에서 POST에서 GET으로 전환하는 방법 (0) | 2020.10.09 |
c # foreach (개체의 속성)…이 작업을 수행하는 간단한 방법이 있습니까? (0) | 2020.10.09 |
Sails.js 대 Meteor-둘 다의 장점은 무엇입니까? (0) | 2020.10.09 |