2010-11-14 16 views
6

No he visto mucha información acerca de Json.NET que admite la deserialización de objetos con campos readonly. Me doy cuenta de que los atributos .NET DataContract y DataMember permiten rellenar los campos readonly durante la deserialización, pero Json.NET no parece soportar esto, al menos desde el comportamiento que estoy viendo.¿Puede Json.NET poblar campos de solo lectura en una clase?

Respuesta

-2

afai puede ver el cambio de un campo a readonly da como resultado un valor de null después de la deserialización. Tenía una muestra de trabajo para otra pregunta (modificada como se muestra a continuación), y ese es el comportamiento que veo.

public class NameAndId 
{ 
    public string name; 
    public int id; 
} 

public class Data 
{ 
    public NameAndId[] data; 
} 

public class Target 
{ 
    public string id; 
    public readonly NameAndId from; 
    public DateTime updated_time; 
    public readonly string message; 
    public Data likes; 
} 

public class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = File.ReadAllText(@"c:\temp\json.txt"); 
     Target newTarget = JsonConvert.DeserializeObject<Target>(json); 
    } 
} 
+0

Sí, ese es el mismo comportamiento que veo. Desafortunadamente, esto junto con las restricciones del constructor sobre los objetos serializados es el factor decisivo para Json.NET para mí. :( –

+0

Supongo que las clases integradas de .Net tienen acceso privilegiado a esos campos que no están disponibles para la biblioteca de terceros. –

+0

No es diferente de configurar cualquier otro campo con reflejo, por lo que es factible y he archivado un solicitud de función en el rastreador de problemas Json.NET. – asgerhallas

9

No es la solución más elegante, pero se puede ampliar el DefaultConstractResolver hacerlo:

public class ContractResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 
     property.Writable = CanSetMemberValue(member, true); 
     return property; 
    } 

    public static bool CanSetMemberValue(MemberInfo member, bool nonPublic) 
    { 
     switch (member.MemberType) 
     { 
      case MemberTypes.Field: 
       var fieldInfo = (FieldInfo)member; 

       return nonPublic || fieldInfo.IsPublic; 
      case MemberTypes.Property: 
       var propertyInfo = (PropertyInfo)member; 

       if (!propertyInfo.CanWrite) 
        return false; 
       if (nonPublic) 
        return true; 
       return (propertyInfo.GetSetMethod(nonPublic) != null); 
      default: 
       return false; 
     } 
    } 
} 

me acaba de quitar un poco de comprobación del método CanSetMemberValue. Desafortunadamente no es ni un método virtual ni un método de instancia, así que también tuve que anular CreateProperty.

1

Esto se puede hacer ahora. Declarar sus propiedades con el atributo JsonProperty, y asegurar que se han declarado un conjunto protegido:

[JsonProperty("Name")] public string Name {get; protected set;} 

Esto no funcionó para mí cuando sólo se utiliza un get, pero funciona perfectamente con el protected set.

Cuestiones relacionadas