Protobuf-net "a reference-tracked object changed reference during deserializartion" error - c#

I am getting a "a reference-tracked object changed reference during deserializartion" error when I deserialize the following object:
[ProtoContract]
public class ZmqMessage
{
[ProtoMember(1)]
public ZmqMessageType MessageType { get; set; }
[ProtoMember(2, DynamicType = true)]
public object MessageBody { get; set; }
public ZmqMessage()
{ }
public ZmqMessage(ZmqMessageType zmqMessageType, object messageBody)
{
this.MessageType = zmqMessageType;
this.MessageBody = messageBody;
}
}
I serialize and deserialize in the following ways:
public static class ProtoBuf
{
public static byte[] Serialize<T>(T serializeThis)
{
using (var stream = new MemoryStream())
{
Serializer.Serialize<T>(stream, serializeThis);
return stream.GetBuffer();
}
}
public static T Deserialize<T>(byte[] byteArray)
{
using (var stream = new MemoryStream(byteArray))
{
return Serializer.Deserialize<T>(stream);
}
}
}
Anything I am doing wrong here?
Thanks
EDIT1: I found out that I don't get the error when I send a string such as "Test" in the MessageBody of the ZmqMessage object. However when I send an int such as (int) 1 or simply 1 it throws above error.
EDIT2: Here is the enum and a quick test case that demonstrates the problem:
public enum ZmqMessageType
{
RawByteArray = 5550,
ControlMessage = 5551
}
ZmqMessage testMessage = new ZmqMessage(ZmqMessageType.ControlMessage, "Test");
byte[] byteMessage = ProtoBuf.Serialize<ZmqMessage>(testMessage);
ZmqMessage deserializedMessage = ProtoBuf.Deserialize<ZmqMessage>(byteMessage);
ZmqMessage testMessage = new ZmqMessage(ZmqMessageType.ControlMessage, (int) 1);
byte[] byteMessage = ProtoBuf.Serialize<ZmqMessage>(testMessage);
ZmqMessage deserializedMessage = ProtoBuf.Deserialize<ZmqMessage>(byteMessage);

Related

How to serialize object to xml with circular dependency in c#?

I've got an object which has a circular dependency
public class Levels
{
public UserDescription user { get; set; }
public List<Levels> friends {get; set;}
public Levels(UserDescription user, List<Levels> friends)
{
this.user = user;
this.friends = friends;
}
public Levels() { }
}
I need to serialize it to xml, so I do the following:
public string SerializeObject(object obj)
{
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
serializer.Serialize(ms, obj);
ms.Position = 0;
xmlDoc.Load(ms);
return xmlDoc.InnerXml;
}
}
This code throws an exception System.InvalidOperationException onserializer = new System.Xml.Serialization.XmlSerializer. How can I solve this?
The problem was that class UserDescription didn't have an empty constructor.

BSon Exception newtonsoft.json

Given
public class Something
{
[JsonProperty(PropertyName = "Ver")]
public string ver { get; set; }
[JsonProperty(PropertyName = "SomethingElse")]
public object somethingElse { get; set; } // will blow up
// public SomethingElse somethingElse { get; set; } // will not
}
public class SomethingElse
{
[JsonProperty(PropertyName = "uuid")]
public Guid uuid { get; set; }
}
Attempting to serialize then deserialize Something will throw Unable cast object of type Guid to Byte[] exception if the member somethingelse of something is an object rather than the type itself.
Sorry for the lack of details. Above was a simplified class that you can serialize but cannot deserialize the object. Below matches are situation more closely, only difference is the dictionary we need is , that will fail as well in the exact same manner. The example works with JSOn, not BSON. The serialization appears valid, just the deserialization throws an exception in the JSonWriter Unable to cast object of type 'System.Guid' to type 'System.Byte[]',line 552
case JsonToken.Bytes:
WriteValue((byte[])reader.Value);<-- is trying to case a Guid to byte array
break;
static void Main(string[] args)
{
const string path = #"C:\zzz_bson.dat";
WriteBson(path);
ReadBson(path);
}
private static void ReadBson(string path)
{
var jsonSerializer = new JsonSerializer();
var file = File.OpenRead(path);
var binaryReader = new BinaryReader(file);
var bsonReader = new BsonReader(binaryReader);
var something = jsonSerializer.Deserialize(bsonReader);
file.Close();
}
private static void WriteBson(string path)
{
//var something = new Dictionary<string, Guid> { { "uuid", new Guid("8afbc8b8-5449-4c70-abd4-3e07046d0f61") } }; //fails
var something = new Dictionary<string, string> { { "uuid", new Guid("8afbc8b8-5449-4c70-abd4-3e07046d0f61").ToString() } }; // works
var jsonSerializer = new JsonSerializer();
var file = File.OpenWrite(path);
var binaryWriter = new BinaryWriter(file);
var bsonWriter = new BsonWriter(binaryWriter);
jsonSerializer.Serialize(bsonWriter, something);
file.Close();
}

DataContractJsonSerializer generic list containing element type's subtypes

I'm going to use DataContractJsonSerializer for JSON serialization/deserialization.
I have two object types in the JSON array and want them both to be deserialized into corresponding object types.
Having the following class defnitions
[DataContract]
public class Post {
[DataMember(Name = "content")]
public String Content { get; set; }
}
[DataContract]
public class User {
[DataMember(Name = "user_name")]
public String UserName { get; set; }
[DataMember(Name = "email")]
public String Email { get; set; }
}
[DataContract]
public class Container {
[DataMember(Name="posts_and_objects")]
public List<Object> PostsAndUsers { get; set; }
}
how can I detect them and deserialize both into the corresponding object type and store in PostsAndUsers property?
If you specific the known types you can serialize and deserialize your class Container, try this code:
protected static Stream GetStream<T>(T content)
{
MemoryStream memoryStream = new MemoryStream();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), new []{typeof(Post), typeof(User)});
serializer.WriteObject(memoryStream, content);
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
protected static T GetObject<T>(Stream stream)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), new[] { typeof(Post), typeof(User) });
return (T)serializer.ReadObject(stream);
}
static void Main(string[] args)
{
var container = new Container {PostsAndUsers = new List<object>()};
container.PostsAndUsers.Add(new Post{Content = "content1"});
container.PostsAndUsers.Add(new User{UserName = "username1"});
container.PostsAndUsers.Add(new Post { Content = "content2" });
container.PostsAndUsers.Add(new User { UserName = "username2" });
var stream = GetStream(container);
var parsedContainer = GetObject<Container>(stream);
foreach (var postsAndUser in parsedContainer.PostsAndUsers)
{
Post post;
User user;
if ((post = postsAndUser as Post) != null)
{
// is post
}
else if ((user = postsAndUser as User) != null)
{
// is user
}
else
{
throw new Exception("");
}
}
}

Serialize ArrayList of Objects

I have an ArrayList which stores a custom object. I want to serialize that ArrayList to a string so I can save it inside the Application settings.
This question looks to resolve it, but is in java. And I am not smart with XML, so could someone help out?
Serialize an ArrayList of Date object type
I have my ArrayList setup:
...
MyObject tempObj = new MyObject("something",1,"something");
MyCollection.Add(tempObj);
...
And I originally had this. It outputs the string, but the object isn't there:
private string SerializeArrayList(ArrayList obj)
{
System.Xml.XmlDocument doc = new XmlDocument();
Type[] extraTypes = new Type[1];
extraTypes[0] = typeof(MyObject);
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), extraTypes);
System.IO.MemoryStream stream = new System.IO.MemoryStream();
try
{
serializer.Serialize(stream, obj);
stream.Position = 0;
doc.Load(stream);
return doc.InnerXml;
}
catch { throw; }
finally
{
stream.Close();
stream.Dispose();
}
}
EDIT: Code request
public class MyObject
{
private string eN;
private Boolean bE;
private int min;
private Boolean bot;
private string onE;
public MyObject(string na, Boolean b)
{
...
}
public MyObject()
{
}
public string GetSomething()
{
...
I tested your code and it seems to work ok, as long as you have [Serializable] on your object.
Also if you are trying to Serialize the fields, you will have to make them public properties.
My Test:
ArrayList array = new ArrayList();
Rules tempObj = new Rules { onE = "Value", min = 45, eN = "Value" };
array.Add(tempObj);
string result = SerializeArrayList(array);
private string SerializeArrayList(ArrayList obj)
{
XmlDocument doc = new XmlDocument();
XmlSerializer serializer = new XmlSerializer(typeof(ArrayList), new Type[]{typeof(Rules)});
using (MemoryStream stream = new System.IO.MemoryStream())
{
try
{
serializer.Serialize(stream, obj);
stream.Position = 0;
doc.Load(stream);
return doc.InnerXml;
}
catch (Exception ex)
{
}
}
return string.Empty;
}
Object:
[Serializable]
[XmlType(TypeName = "Rules")]
public class Rules
{
// Make fields propertys so they will be serialized
public string eN { get; set; } //Name
public Boolean bE { get; set; } //Whether blocked entirely
public int min { get; set; } //Minutes they are allowed if blocked
public Boolean bot { get; set; } //Create notification if allowance exceed
public string onE { get; set; } //Nothing or CLOSE Process
public Rules(string na, Boolean b)
{
}
public Rules()
{
}
}
I ran into a similar problem, and there is this great program called SharpSerializer, which is available through Nuget. It will handle your ArrayList quite easily, just type the code:
SharpSerializer mySerializer = new SharpSerializer();
mySerializer.Serialize(ArrayList, "filetosaveto.xml");
Here's the link to the website, its free so don't worry about paying anything:
http://www.sharpserializer.com/en/index.html

Parse XML file and populate object with values

After I send a request with the required parameters in the response I get the following XML:
<content>
<main>
<IMGURL>image url</IMGURL>
<IMGTEXT>Click Here</IMGTEXT>
<TITLE>image title</TITLE>
<IMGLINK>image link</IMGLINK>
</main>
</content>
and I also made the following two classes:
[Serializable]
public class content
{
private Main _main;
public content()
{
_main = new Main();
}
public Main Main
{
get { return _main; }
set { _main = value; }
}
}
[Serializable]
public class Main
{
public string IMGURL { get; set; }
public string IMGTEXT { get; set; }
public string TITLE { get; set; }
public string IMGLINK { get; set; }
}
While debugging I can see that in the response I get the wanted results. However I'm having troubles deserializing the XML and populating the object.
Call to the method:
public static class ImageDetails
{
private static string _url = ConfigurationManager.AppSettings["GetImageUrl"];
public static content GetImageDetails(string ua)
{
var contenta = new content();
_url += "&ua=" + ua;
try
{
WebRequest req = WebRequest.Create(_url);
var resp = req.GetResponse();
var stream = resp.GetResponseStream();
//var streamreader = new StreamReader(stream);
//var content = streamreader.ReadToEnd();
var xs = new XmlSerializer(typeof(content));
if (stream != null)
{
contenta = (content)xs.Deserialize(stream);
return contenta;
}
}
catch (Exception ex)
{
}
return new content();
}
}
The serializer is case-sensitive. You either need to rename the property content.Main to main or add the attribute [XmlElement("main")] to it.

Categories