BSon Exception newtonsoft.json - c#

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();
}

Related

how to Json DeserializeObject specified type of string

ok i'm trying to serialize object and deserialize it back,
i'm using these classes to handle receiving different types
public class JsonWrapper
{
public string ObjType { get; set; }
public object Obj { get; set; }
}
public class JsonWrapper<T>
{
public string ObjType => typeof(T).FullName;
public T Obj { get; set; }
}
its working like that
var wrapper = new JsonWrapper<Car> {Obj = new Car {model = 2012, Color = "red"}};
var serialized = JsonConvert.SerializeObject(wrapper);
var deserialized = JsonConvert.DeserializeObject<JsonWrapper>(serialized);
var type = Type.GetType(deserialized.ObjType);
var message = JsonConvert.DeserializeObject(
Convert.ToString(deserialized.Obj), type);
my problem is what if i want to use the wrapper for string type, if i tried the same way with string
var wrapper = new JsonWrapper<string> {Obj = "hello"};
var serialized = JsonConvert.SerializeObject(wrapper);
var deserialized = JsonConvert.DeserializeObject<JsonWrapper>(serialized);
var type = Type.GetType(deserialized.ObjType);
var message = JsonConvert.DeserializeObject(
Convert.ToString(deserialized.Obj), type);
it doesn't work and get me error
Unexpected character encountered while parsing value: h. Path '', line 1, position 1
working with int as well so i wondering
Disregarding my opinions on whether or not you should be doing this or the usefulness of it.
Given
public class JsonWrapper<T>
{
public string ObjType => typeof(T).FullName;
public T Obj { get; set; }
}
Unwrap method
public static object UnWrap(string json)
{
var jObject = JObject.Parse(json);
var objType = (string)jObject["ObjType"];
if(string.IsNullOrWhiteSpace(objType))
throw new InvalidOperationException("objType cannot be null or WhiteSpace");
var type = Type.GetType(objType) ?? throw new ArgumentNullException("Type.GetType(objType)");
var result = jObject["Obj"]?.ToObject(type) ?? throw new ArgumentNullException("jObject[\"Obj\"]?.ToObject(type)");
return result;
}
Note : this was just a quick attempt at fault tolerance, the handling should likely be better with more appropriate exception type.
Usage
var wrapper = new JsonWrapper<string> { Obj = "hello" };
var serialized = JsonConvert.SerializeObject(wrapper);
var result = UnWrap(serialized);
Console.WriteLine(result.GetType().Name);
var wrapper2 = new JsonWrapper<Version> { Obj = new Version(1,2,3,4) };
var serialized2 = JsonConvert.SerializeObject(wrapper2);
result = UnWrap(serialized2);
Console.WriteLine(result.GetType().Name);
Output
String
Version

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

Deserialize a restful uri

I'm trying to deserialize a rest uri located at http://ws.geonames.org/countryInfo?lang=it&country=DE and keep getting error (There is an error in XML document (1, 1)). Plug http://ws.geonames.org/countryInfo?lang=it&country=DE into the browser and you can see the result.
I have a class
public class Country
{
public string CountryName {get;set;}
public string CountryCode {get;set;}
}
and the method in my console app is as follows:
static void DeserializeTheXML()
{
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "countryName";
xRoot.IsNullable = true;
XmlSerializer ser = new XmlSerializer(typeof(Country), xRoot);
XmlReader xRdr = XmlReader.Create(new StringReader("http://ws.geonames.org/countryInfo?lang=it&country=DE"));
Country tvd = new Country();
tvd = (Country)ser.Deserialize(xRdr);
Console.WriteLine("Country Name = " + tvd.CountryName);
Console.ReadKey();
}
any ideas on how to deserialize this rest service? thanks..
For serialization to work successfully you need to decorate your objects with the proper serialization attributes or use the XmlAttributeOverrides constructor. Also don't forget that XML is case sensitive and your objects must reflect the XML structure you are deserializing:
public class GeoNames
{
[XmlElement("country")]
public Country[] Countries { get; set; }
}
public class Country
{
[XmlElement("countryName")]
public string CountryName { get; set; }
[XmlElement("countryCode")]
public string CountryCode { get; set; }
}
class Program
{
static void Main()
{
var url = "http://ws.geonames.org/countryInfo?lang=it&country=DE";
var serializer = new XmlSerializer(typeof(GeoNames), new XmlRootAttribute("geonames"));
using (var client = new WebClient())
using (var stream = client.OpenRead(url))
{
var geoNames = (GeoNames)serializer.Deserialize(stream);
foreach (var country in geoNames.Countries)
{
Console.WriteLine(
"code: {0}, name: {1}",
country.CountryCode,
country.CountryName
);
}
}
}
}

Deserializing JSON to Object

I'm receiving JSON, that i need to Deserialize. I'm using JavaScriptSerializer to do so.
E.g. Objects
class Player
{
public string name{ set; get; }
public float yPos { set; get; }
public float xPos { set; get; }
}
class Communication
{
public string id{ set; get; }
public string message{ set; get; }
public string status{ set; get; }
}
E.g. JSONs:
var json1 = "[{\"name\":\"Master\",\"xPos\":\"34.67\",\"yPos\":\"85.36\"}, {\"name\":\"Puppet\",\"xPos\":\"19.56\",\"yPos\":\"75.19\"}]";
var json2 = "[{\"id\":\"5697862\",\"message\":\"Hello\",\"status\":\"85.36\"}, {\"id\":\"4698458\",\"message\":\"Hi\",\"status\":\"75.19\"}]";
Deserializer Method:
private static List<T> Deserialize<T>(string json)
{
var s = new System.Web.Script.Serialization.JavaScriptSerializer();
List<T> obj = s.Deserialize<List<T>>(json);
return obj;
}
But here is the problem I have two different kind of JSON messages coming. So how do I figure out to what object I need to Deserialize?
Instead of deserializing to a specific class you can process the result dynamically
var js = new JavaScriptSerializer();
dynamic dynObj = js.DeserializeObject(jsonN);
foreach (var obj in dynObj)
{
if (obj.ContainsKey("name")) Console.WriteLine(obj["name"]);
else Console.WriteLine(obj["message"]);
}
I would recommend taking a look at the DataContractJsonSerializer (which can also deserialize). This class ensures that you are following the specific contract when you serialize and deserialize to and from JSON, respectively.
For deserialization, it works something like this:
stream1.Position = 0;
Person p2 = (Person)ser.ReadObject(stream1);
Serialization works like this:
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
ser.WriteObject(stream1, p);
See the link for additional explanation.

Categories