We found out why it does not work. Immediately after serializing the object, we identify the resulting string for greater readability. Then we write the line to the file:
public void SaveContractToJSON<T>(T contract, string filePath) { using (MemoryStream stream = new MemoryStream()) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); serializer.WriteObject(stream, contract); string json = Encoding.UTF8.GetString(stream.ToArray()); File.WriteAllText(filePath, json.IndentJSON()); } }
Identification is actually the reason that deserialization did not work. The DataContractJsonSerializer parser seems to be really picky. If some characters are between the {character and the "__type" field, the serializer is lost.
For example, this line will be serialized correctly:
"{\"Elements\":[{\"__type\":\"ElementA:#Data\",\"Id\":1}]}"
But this next line will not be serialized.
"{\"Elements\":[ {\"__type\":\"ElementA:#Data\",\"Id\":1}]}"
The only difference is the space characters before "__type". Serialization will raise a MemberAccessException. This is misleading because this behavior only appears when deserializing into an abstract list. Serialization in an abstract field works fine regardless of characters.
To fix this problem without deleting the readability of the file, this line can be changed before deletion. For example:
public T LoadContractFromJSON<T>(string filePath) { try { string text = File.ReadAllText(filePath); text = Regex.Replace(text, "\\{[\\n\\r ]*\"__type", "{\"__type"); using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(text))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); T contract = (T)serializer.ReadObject(stream); return contract; } } catch (System.Exception ex) { logger.Error("Cannot deserialize json " + filePath, ex); throw; } }
noon Oct 19 '10 at 22:59 2010-10-19 22:59
source share