Tenho um projeto de API da Web sendo configurado assim:
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
No entanto, quero que a caixa das chaves do dicionário permaneça inalterada. existe algum atributo em que Newtonsoft.Json
eu possa usar para uma classe para denotar que desejo que a capitalização permaneça inalterada durante a serialização?
public class SomeViewModel
{
public Dictionary<string, string> Data { get; set; }
}
Respostas:
Não há um atributo para fazer isso, mas você pode fazer isso personalizando o resolvedor.
Vejo que você já está usando um
CamelCasePropertyNamesContractResolver
. Se você derivar uma nova classe de resolução dessa classe e substituir oCreateDictionaryContract()
método, poderá fornecer umaDictionaryKeyResolver
função substituta que não altera os nomes das chaves.Aqui está o código de que você precisa:
Demo:
Aqui está o resultado do acima. Observe que todos os nomes de propriedade de classe são caseiros, mas as chaves do dicionário mantiveram sua caixa original.
fonte
contract.DictionaryKeyResolver = key => key;
funciona bem.DictionaryKeyResolver
somente se minha propriedade Dicionário tiver algum atributo personalizado?Json.NET 9.0.1 introduziu a
NamingStrategy
hierarquia de classes para lidar com esse tipo de problema. Ele extrai a lógica para o remapeamento algorítmico de nomes de propriedade do resolvedor de contratos para uma classe leve e separada que permite o controle de chaves de dicionário , nomes de propriedades explicitamente especificados e nomes de dados de extensão (em 10.0.1 ) são remapeados.Ao usar
DefaultContractResolver
e definirNamingStrategy
para uma instância de,CamelCaseNamingStrategy
você pode gerar JSON com nomes de propriedade camel-case e chaves de dicionário não modificadas definindo-o emJsonSerializerSettings.ContractResolver
:Notas:
A implementação atual de
CamelCasePropertyNamesContractResolver
também especifica que os membros .Net com nomes de propriedades explicitamente especificados (por exemplo, aqueles ondeJsonPropertyAttribute.PropertyName
foi definido) devem ter seus nomes remapeados:A
resolver
descrição acima preserva esse comportamento. Se você não quer isso, definaOverrideSpecifiedNames = false
.Json.NET tem várias estratégias de nomenclatura integradas, incluindo:
CamelCaseNamingStrategy
. Uma estratégia de nomenclatura de caixa de camelo que contém a lógica de remapeamento de nome incorporada anteriormenteCamelCasePropertyNamesContractResolver
.SnakeCaseNamingStrategy
. Uma estratégia de nomenclatura de caso de cobra .DefaultNamingStrategy
. A estratégia de nomenclatura padrão. Os nomes das propriedades e as chaves de dicionário permanecem inalterados.Ou você pode criar seu próprio herdando da classe base abstrata
NamingStrategy
.Embora também seja possível modificar o
NamingStrategy
de uma instância deCamelCasePropertyNamesContractResolver
, uma vez que o último compartilha informações de contrato globalmente em todas as instâncias de cada tipo , isso pode levar a efeitos colaterais inesperados se seu aplicativo tentar usar várias instâncias deCamelCasePropertyNamesContractResolver
. Esse problema não existe comDefaultContractResolver
, por isso é mais seguro usar quando qualquer customização da lógica de caixa é necessária.fonte
public Dictionary<string, Dictionary<string, string>> Values { get; set; }
. Ele ainda faz camelCase para as chaves do dicionário interno.CamelCasePropertyNamesContractResolver
. Basicamente,NamingStrategy
para o primeiro influenciaria os contratos gerados pelo segundo. Isso pode ser o que você está vendo. Experimente a nova recomendação e me informe se ela corrige seu problema.NamingStrategy
, de modo que seja capaz de analisar ambas as caixas camel e pascal?config
deveria ser?config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
. Parece ser a API da Web MVC 4HttpConfiguration
, consulte Como definir JsonSerializerSettings personalizado para Json.NET na API da Web MVC 4? .Essa é uma resposta muito boa. Mas por que não simplesmente substituir o
ResolveDictionaryKey
?fonte
A resposta selecionada é perfeita, mas acho que, no momento em que estou digitando isso, o resolvedor de contratos deve mudar para algo assim porque DictionaryKeyResolver não existe mais :)
fonte
DictionaryKeyResolver
foi adicionado na versão 7.0.1 ePropertyNameResolver
foi marcado como obsoleto.