2011-09-12 15 views
12

Sto utilizzando un DataContractJsonSerializer e ho un problema con il Nome DataMember.Serialization DataMember (name) override issue

Ho creato una classe base e diverse classi derivate. Ho bisogno delle classi derivate perché ho diverse stringhe json. Voglio deserializzare le stringhe JSON e quindi ho bisogno di nomi diversi per i datamembers. Io cerco di cambiare il nome DataMember come nel seguente esempio:

BaseClass:

[DataContract] 
public abstract class BaseClass 
{ 


    [DataMember] 
    public virtual string FirstMethod { get; protected set; } 

} 

classe derivata:

[DataContract] 
[KnownType(typeof(BaseAccess))] 
public class DerivedClass 
{ 


    [DataMember(Name="first_method")] 
    public virtual string FirstMethod { get; protected set; } 

} 

Il problema è che quando uso una classe derivata la serializzazione sembra ignorare il nome DataMember specificato. Quindi, quando deserializzo con il tipo DerivedClass, la serializzazione sembra avvenire con il nome "FirstMethod" (della classe base) anziché "first_method" (della classe derivata). È possibile utilizzare il nome DataMember della classe derivata (che è diversa per diverse classi derivate nella mia situazione).

Un'altra domanda. Ho trovato esempi con KnownType aggiunto alla classe base e aggiunto alla classe derivata. Sembra logico per me farlo sulla classe derivata (specialmente per problemi di ereditarietà). Cosa è corretto?

risposta

7

Ho avuto lo stesso problema. Stavo usando VB.NET e dovevo Shadow (o Overload) della proprietà per far sì che WCF rispettasse la proprietà DataMember nella mia classe derivata. In C# dovresti essere in grado di utilizzare il nuovo operatore.

public class DerivedClass 
{ 
    [DataMember(Name = "first_method")] 
    new public string FirstMethod { get; protected set; } 
} 
+0

Si noti che per evitare di creare due campi in JSON, sarà necessario rimuovere l'attributo [DataMember] dalla proprietà nella classe base. –

3

Il trucco è specificare EmitDefaultValue = false per il membro dati virtuale della classe base, e nella sua attuazione nel valore predefinito di classe di ritorno derivata in modo che il membro di dati non è serializzato. Nella classe derivata definire un altro membro dati con il nome richiesto.

[DataContract(Name = "baseclass", Namespace = "")] 
[KnownType(typeof(DerivedClass))] 
public class BaseClass 
{ 
    [DataMember(Name = "attributes", EmitDefaultValue = false)] 
    public virtual SomeType Fields { get; set; } 
} 

[DataContract(Name = "derivedclass", Namespace = "")] 
public class DerivedClass : BaseClass 
{ 
    public override SomeType Fields 
    { 
     get { return null; } 
    } 

    [DataMember(Name = "fields")] 
    public SomeType DerivedFields 
    { 
     get { return base.Fields; } 
    } 
}