0

This example code is a simplified version of my project, the _lockObject is legacy and cannot be removed I have the following class

 [DataContract(IsReference = true)]
 public class test 
 {
     [DataMember]
     private static object _lockObject = new object();
     [DataMember]
     private int num;
 }

And I try to serialize it using Json.NET as follows :

StringBuilder sb = new StringBuilder();
TextWriter text = new StringWriter(sb);

var serializer = new JsonSerializer();
serializer.TypeNameHandling = TypeNameHandling.Auto;

serializer.PreserveReferencesHandling = PreserveReferencesHandling.None;
serializer.NullValueHandling = NullValueHandling.Ignore;
serializer.TraceWriter = new MemoryTraceWriter();
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;

serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
serializer.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full;

var test = new test();
serializer.Serialize(text, test);

I get an error

Error getting value from '_lockObject'

If i remove the static from _lockObject the serialization is successful

Shachaf.Gortler
  • 5,655
  • 14
  • 43
  • 71
  • 1
    Why are you trying to serialize a private member that holds no meaningful data, used only for locking (I assume?) If you want to serialize the poorly named `num`, you should create a property. – Jodrell Mar 25 '14 at 12:19
  • This example code is a simplified version of my project, the _lockObject is legacy and cannot be removed – Shachaf.Gortler Mar 25 '14 at 12:23
  • fine but, you don't need to serialize it. Another `new object`, when the JSON is deserialized would do just as well, the member variable carries no state. – Jodrell Mar 25 '14 at 12:26
  • This is a legacy class , the _lockObject must be serialzed – Shachaf.Gortler Mar 25 '14 at 12:27
  • Explain why it must be serialized? Does some recipient of the JSON rely on that attributes presence? – Jodrell Mar 25 '14 at 12:30
  • The legacy business logic depends on it being serialized. – Shachaf.Gortler Mar 25 '14 at 12:33
  • To put it another way, `_lockObject` is not a `DataMember` because it embodies no datum. – Jodrell Mar 25 '14 at 12:34
  • Really? Why have you made it `static` then? It can't be serialised as part of an instance and be static across all instances? – Jodrell Mar 25 '14 at 12:35
  • I have not maid it this way , this the way the legacy system is designed, I agree it is not the best design but this the way it is. – Shachaf.Gortler Mar 25 '14 at 12:38
  • So, how does the legacy serialization work? The serialization that feeds the legacy business logic? What value does that put in the JSON for the `_lockObject` attribute? – Jodrell Mar 25 '14 at 12:39
  • The legacy system is based on WCF with DataContractSerializer – Shachaf.Gortler Mar 25 '14 at 12:40
  • 1
    Hope this help: http://stackoverflow.com/questions/17222900/serialize-object-along-with-static-member-variables-to-xml – noobob Mar 25 '14 at 12:43

2 Answers2

3

The problem is that _lockObject is static field. Static fields are not serializable by default. And IMO you shouldn't serialize it.

  • This is not true , private members with no setters and getters are also serialized. Also if i remove the static from _lockObject the serialization works – Shachaf.Gortler Mar 25 '14 at 12:25
1

Allowing a lock object to be deserialized into is a bad idea because it allows the locking mechanism to be defeated. If you're just looking for a way to satisfy legacy serialization requirements without screwing up your locking mechanism, I propose that you introduce a dummy non-static member to stand in for the lock object on serialization and deserialization. Define your class like this instead:

[DataContract(IsReference = true)]
public class test 
{
    // DO NOT include this in serialization
    private static object _lockObject = new object();

    // This dummy object stands in for _lockObject for purposes of serialization
    // but is not referenced elsewhere in the code
    [DataMember(Name = "_lockObject")]
    private object dummy = new object();

    [DataMember]
    private int num;
}

The code can continue to reference the static _lockObject, while the external world sees the value of the dummy object instead, and is none the wiser. Now the value of _lockObject cannot be inadvertently changed through deserialization.

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300