¿Cómo puedo cambiar los nombres de propiedad al serializar con Json.net?

434

Tengo algunos datos en un objeto C # DataSet. Puedo serializarlo ahora mismo usando un convertidor Json.net como este

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

Sin embargo, esto utiliza los nombres de propiedad de datacuando imprime en el archivo .json. Me gustaría cambiar los nombres de las propiedades para que sean algo diferente (por ejemplo, cambiar 'foo' a 'bar').

En la documentación de Json.net , en 'Serialización y deserialización de JSON' → 'Atributos de serialización' dice "JsonPropertyAttribute ... permite personalizar el nombre". Pero no hay ejemplo. ¿Alguien sabe cómo usar un JsonPropertyAttribute para cambiar el nombre de la propiedad a otra cosa?

( Enlace directo a la documentación )

La documentación de Json.net parece ser escasa. Si tienes un gran ejemplo, intentaré que se agregue a la documentación oficial. ¡Gracias!

culix
fuente
3
Para su información, hay un ejemplo de esto en la documentación en Muestras -> Serialización de JSON -> JsonPropertyAttribute name . No estoy seguro de en qué punto se agregó.
Brian Rogers

Respuestas:

791

Puede decorar la propiedad que desea controlar su nombre con el [JsonProperty]atributo que le permite especificar un nombre diferente:

using Newtonsoft.Json;
// ...

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

Documentación: Atributos de serialización

Darin Dimitrov
fuente
1
¿Requiere esto que lea mis datos en un objeto personalizado que creo en lugar de un conjunto de datos?
culix
3
@culix, sí, requiere el uso de un modelo. Un DataSet es una estructura débilmente tipada, por lo que hablar de nombres de propiedades no es muy lógico.
Darin Dimitrov
76
Como taquigrafía, también puedes hacerlo[JsonProperty("FooBar")]
Bart Verkoeijen
2
@DarinDimitrov ¿hay alguna manera de hacer esto sin Json .NET?
CH81
12
Sin embargo, usar un modelo es fácil, simplemente tome una muestra de su JSON y péguelo en un archivo .cs vacío usando "Pegado especial" -> "Pegar JSON como clases". - Está integrado en Visual Studio. - A partir de ahí, básicamente solo necesita configurar cosas como mayúsculas / minúsculas para cambiar el nombre de las convenciones de nomenclatura .NET, etc. (usando un convertidor de mayúsculas y minúsculas para el primero y el atributo JsonProperty para el último).
BrainSlugs83
71

Si no tiene acceso a las clases para cambiar las propiedades, o no desea usar siempre la misma propiedad de cambio de nombre, el cambio de nombre también se puede hacer creando un resolutor personalizado.

Por ejemplo, si tiene una clase llamada MyCustomObject, que tiene una propiedad llamada LongPropertyName, puede usar un resolutor 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;
  }
}

Luego solicite la serialización y suministre el resolutor:

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

Y el resultado se acortará a {"Short": "prop value"} en lugar de {"LongPropertyName": "prop value"}

Más información sobre solucionadores personalizados aquí

StingyJack
fuente
1
Esta es una mejor solución si su clase para serializar se declara en otro ensamblado que incluye una versión diferente del paquete Newtonsoft.Json. (Puede que ni siquiera arroje ningún error). El DefaultContractResolverdebe ser puesto en el mismo conjunto, donde se utiliza el método JsonConvert.Serialize ().
Artemious
6

Todavía hay otra forma de hacerlo, que es usar una NamingStrategy particular , que se puede aplicar a una clase o una propiedad al decorarlas con [JSonObject]o [JsonProperty].

Existen estrategias de nomenclatura predefinidas CamelCaseNamingStrategy, pero puede implementar las suyas propias.

La implementación de diferentes estrategias de nombres se puede encontrar aquí: https://github.com/JamesNK/Newtonsoft.Json/tree/master/Src/Newtonsoft.Json/Serialization

JotaBe
fuente
3
Si puede, comparta un ejemplo de una implementación personalizada de NamingStrategy
usuario1007074
Por supuesto no. Deberías haberlo hecho solo, pero te ahorraré el tiempo para decirte que simplemente tienes que heredar newtonsoft.com/json/help/html/... Puedes ver la implementación de las clases existentes y crear la tuya propia.
JotaBe
Gracias. Debería haber actualizado mi comentario: de hecho, gracias a la gloria que es GitHub, uno puede usar una de las implementaciones de Newtonsoft como ejemplo, por ejemplo, este
user1007074
8
@JotaBe, ese no es el espíritu de stackoverflow. Y como un programador que solo quiere hacer mi trabajo, francamente, hubiera sido mil veces mejor para mí levantar el código que podría haber proporcionado. Y ustedes también tendrían mi voto. Tengo 18 años de experiencia en codificación y TripleByte me clasifica como "experto" en c #. No TODOS los problemas deben dejarse como un "ejercicio para el lector". A veces solo queremos hacer nuestro trabajo y seguir adelante.
bboyle1234
2
Estoy de acuerdo con usted, y no suelo escribir este tipo de comentarios. Sin embargo, puedo asegurar que, en este caso, mirar el código vinculado es mucho mejor que cualquier explicación que pueda dar. Y json.net es una biblioteca de código abierto muy bien documentada. Enlace incluido a las implementaciones (ejemplos perfectos)
JotaBe