Como posso alterar os nomes das propriedades ao serializar com o Json.net?

434

Eu tenho alguns dados em um objeto C # DataSet. Eu posso serializá-lo agora usando um conversor Json.net como este

DataSet data = new DataSet();
// do some work here to populate 'data'
string output = JsonConvert.SerializeObject(data);

No entanto, isso usa os nomes de propriedades dataao imprimir no arquivo .json. Gostaria de mudar o nome da propriedade para algo diferente (digamos, mude 'foo' para 'bar').

Na documentação do Json.net , em 'Serializando e desserializando JSON' → 'Serialization Attributes', ele diz "JsonPropertyAttribute ... permite que o nome seja personalizado". Mas não há exemplo. Alguém sabe como usar um JsonPropertyAttribute para alterar o nome da propriedade para outra coisa?

( Link direto para a documentação )

A documentação do Json.net parece ser escassa. Se você tiver um ótimo exemplo, tentarei adicioná-lo à documentação oficial. Obrigado!

culix
fonte
3
Para sua informação, há um exemplo disso na documentação em Samples -> Serializing JSON -> JsonPropertyAttribute name . Não tenho certeza em que ponto foi adicionado.
Brian Rogers

Respostas:

791

Você pode decorar a propriedade que deseja controlar seu nome com o [JsonProperty] atributo que permite especificar um nome diferente:

using Newtonsoft.Json;
// ...

[JsonProperty(PropertyName = "FooBar")]
public string Foo { get; set; }

Documentação: Atributos de serialização

Darin Dimitrov
fonte
1
Isso requer que eu leia meus dados em um objeto personalizado criado em vez de um DataSet?
culix
3
@culix, sim, requer o uso de um modelo. Um DataSet é uma estrutura de tipo fraco, portanto, falar sobre nomes de propriedades não é muito lógico.
Darin Dimitrov
76
Como uma abreviação, você também pode fazer[JsonProperty("FooBar")]
Bart Verkoeijen
2
@DarinDimitrov, existe uma maneira de fazer isso sem o Json .NET?
CH81
12
Porém, é fácil usar um modelo, basta pegar uma amostra do seu JSON e colá-lo em um arquivo .cs vazio usando "Colar Especial" -> "Colar JSON como Classes". - Está embutido no Visual Studio. - A partir daí, você basicamente precisa configurar as coisas como maiúsculas / minúsculas para usar as convenções de nomenclatura do .NET etc. (usando um conversor de maiúsculas e minúsculas para o primeiro e o atributo JsonProperty para o segundo).
BrainSlugs83
71

Se você não tem acesso às classes para alterar as propriedades ou não deseja sempre usar a mesma propriedade de renomeação, a renomeação também pode ser feita criando um resolvedor personalizado.

Por exemplo, se você tem uma classe chamada MyCustomObject, que possui uma propriedade chamada LongPropertyName, pode usar um resolvedor personalizado como este…

public class CustomDataContractResolver : DefaultContractResolver
{
  public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver ();

  protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
  {
    var property = base.CreateProperty(member, memberSerialization);
    if (property.DeclaringType == typeof(MyCustomObject))
    {
      if (property.PropertyName.Equals("LongPropertyName", StringComparison.OrdinalIgnoreCase))
      {
        property.PropertyName = "Short";
      }
    }
    return property;
  }
}

Em seguida, chame a serialização e forneça o resolver:

 var result = JsonConvert.SerializeObject(myCustomObjectInstance,
                new JsonSerializerSettings { ContractResolver = CustomDataContractResolver.Instance });

E o resultado será reduzido para {"Short": "prop value"} em vez de {"LongPropertyName": "prop value"}

Mais informações sobre resolvedores personalizados aqui

StingyJack
fonte
1
Essa é uma solução melhor se sua classe para serializar for declarada em outro assembly que inclua uma versão diferente do pacote Newtonsoft.Json. (pode até não gerar nenhum erro). Ele DefaultContractResolverdeve ser colocado no mesmo assembly em que o método JsonConvert.Serialize () é usado.
Artemious
6

Ainda existe outra maneira de fazer isso: usar uma NamingStrategy específica , que pode ser aplicada a uma classe ou propriedade decorando-as com [JSonObject]ou[JsonProperty] .

Existem estratégias de nomenclatura predefinidas, como CamelCaseNamingStrategy , mas você pode implementar suas próprias.

A implementação de diferentes estratégias de nomenclatura pode ser encontrada aqui: https://github.com/JamesNK/Newtonsoft.Json/tree/master/Src/Newtonsoft.Json/Serialization

JotaBe
fonte
3
Se você puder, compartilhe um exemplo de implementação personalizada da NamingStrategy
user1007074
Claro que não. Você deveria ter feito isso sozinho, mas pouparei tempo para lhe dizer que você simplesmente precisa herdar newtonsoft.com/json/help/html/…. Você pode ver a implementação das classes existentes e criar a sua própria.
Jotabe
Obrigado - eu deveria ter atualizado meu comentário: de fato, graças à glória do GitHub, pode-se usar uma das implementações da Newtonsoft como exemplo, por exemplo, esta
user1007074
8
@ JotaBe, esse não é o espírito do stackoverflow. E, como programador que apenas quer fazer meu trabalho, francamente, teria sido mil vezes melhor para eu elevar o código que você poderia ter fornecido. E você teria o meu voto também. Tenho 18 anos de experiência em codificação e sou classificado pela TripleByte como "especialista" em c #. Nem todo problema precisa ser deixado como um "exercício para o leitor". Às vezes, apenas queremos fazer nosso trabalho e seguir em frente.
precisa saber é o seguinte
2
Eu concordo com você e geralmente não escrevo esse tipo de comentário. No entanto, posso garantir que, nesse caso, olhar o código vinculado é muito melhor do que qualquer explicação que eu possa dar. E o json.net é uma biblioteca de código aberto muito bem documentada. Link incluído para as implementações (exemplos perfeitos)
JotaBe 02/04