Serializing Guid to MongoDB as a BsonString and not BinData? - c#

I have a class that has the following property
[BsonId]
public Guid EventId { get; private set; }
I would like to serialize(and deserialize) the class that has this property to MongoDB with the use of the ToBsonDocument method. Though through the use of the default serializer the resulting BSON type for the _id field is
"_id" : BinDate(3, "wX9ZnP0ApEWF0d5aXLgiUA==")
I would like it to be stored as a BsonString. I plan to create a custom SerializerBase<> extension class in the future to properly deserialize the string back to a Guid I just have not gotten there yet.
I know that I could simply change my property to be a String
[BsonId]
public String EventId { get; private set; }
But I would like to keep it as a Guid. I think to solve my problem I need to make use of a serialization tag but I am not sure which one, any ideas?

Actually I somehow managed to find my answer right after I posted this question.
By making use of the tag BsonRepresentation I can specify the BSON data type that I would like MongoDB to use when serializing the data.
[BsonRepresentation(BsonType.String)]

Related

How to change xml attribute while deserialization with xmlserializer c#?

Is there any way of modifying attribute value when deserializing xml using XmlSerializer?
For instance, I have such xml:
<chunkList>
<chunk id="ch1" type="p">
<sentence id="s1">
<tok>
<orth>XXX</orth>
<lex disamb="1">
<base>XXX</base>
<ctag>subst:sg:nom:f</ctag>
</lex>
</tok>
</sentence>
</chunk>
</chunkList>
I want to deserialize chunk element into Chunk class and set attribute id="ch1" to Id property - is there any way of trimming this ch substring and asigning number 1 to property of type int?
[XmlAttribute("id")] //maybe there is some attribute to achive this?
public int Id { get; set; }
I have read some of MSDN documentation but didn't found any solution.
There is no elegant way to achieve this using a single attribute. The only way I know to achieve the desired result is to make use of [XmlIgnore] and to create a second property specifically for the stringified xml ID, and a localized converter property for your internal integer value. Some along the lines of:
[XmlAttribute("id")]
public string _id_xml {get; set;}
[XmlIgnore]
public int Id {
// convert local copy of xml attribute value to/from int.
get => int.Parse(_id_xml.Replace("ch",""));
set => _id_xml = $"ch{value}";
}
My converter here is very basic and clearly you will need to improve it and consider error handling.
The serializer will operate against the [XmlAttribute] as normal, but pass over the [XmlIgnore]. Your c# code could use either.
Unfortunately, the XmlSerializer requires public properties, so you can not hide the _id_xml property from your code, but you could use [Obsolete] to signal a warning in the compiler.
You could do the conversion to/from int with the _id_xml getter & setter, but doing this could be problematic when managing errors during serialization.

Use ObjectId.GenerateNewId() or leave MongoDB to create one?

In C# I can use the ObjectId.GenerateNewId() to generate ObjectId values.
Most of the time when I insert a document in a collection I do not set the value of _id fields. MongoDB creates the ObjectId values automatically.
I would like to ask if it is safe to set it manually by using the ObjectId.GenerateNewId() method.
When you insert a new mongodb document the son driver check if exist a property with the BsonId AttributeClass. If exist and is null it create a new ObjectId, if doesn't exist during the document insertion mongodb will generate e new ObjectId.
Sometimes users encounter problem with "only zero" ObjectId, for this reason my suggestion is to use a combination of BsonID attribute class and ObjectId.GenerateNewId so you are sure that that property will not have weird behaviour.
e.g.
public class SomeClass {
[BsonId]
public ObjectId MySuperId { get; set; }
public SomeClass() {
this.MySuperId = ObjectId.GenerateNewId();
}
}

I want to declare a property name as Line#

I have a Json data returning from service which contains field like Line# and others
I am creating Model class which will have property names same as the these filed. I will map the Json data and model class since the field name are same it will automatically map the values.
problem what i am facing is i cannot declare property name as Line# [against coding guidelines gives error]
Is there any alternative way for this?
If you're using Json.NET (and if you're not, you should probably look into it), you can specify the serialized member name with the JsonProperty attribute:
[JsonProperty("Line#")]
public int LineNumber { get; set; }
If you're using the built-in DataContractJsonSerializer, specify the name in the DataMember attribute:
[DataMember(Name = "Line#")]
public int LineNumber { get; set; }

Deserialize json array data in c# [duplicate]

I need to deserialize some JavaScript object represented in JSON to an appropriate C# class. Given the nice features of automatic properties, I would prefer having them in these classes as opposed to just having fields. Unfortunately, the .NET serialization engine (at least, by default) totally ignores automatic properties on deserialization and only cares about the backing field, which is obviously not present in the JavaScript object.
Given that there's no standard way to name backing fields and to be honest I don't even want to bother with the "let's create a JavaScript object that looks like it had C# backing fields" approach as it sounds a bit dirty, the only way I could serialize JavaScript fields to C# auto-properties if I could force the serialization engine to somehow ignore the backing field and use the property directly. Unfortunately, I can't figure out how this is done or if this can be done at all. Any ideas would be appreciated.
EDIT: Here's an example:
Javascript:
function Cat()
{
this.Name = "Whiskers";
this.Breed = "Tabby";
}
var cat = new Cat();
This is then serialized to "{Name: 'Whiskers'}".
The C# class:
[Serializable()]
public class Cat
{
public string Name { get; set; }
public string Breed { get; set; }
}
And the deserialization code, that fails:
new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream);
And it is apparent from the exception that it fails because it is looking for the backing field.
EDIT2: Here's the exception, if that helps (no inner exceptions):
System.Runtime.Serialization.SerializationException
"The data contract type 'Test.Cat'
cannot be deserialized because the
required data members
'<Name>k__BackingField, <Breed>k__BackingField' were not
found."
What's happening here is the deserializer is trying to guess the name of your backing fields.
You can solve this by adding explicit mappings (DataContract/DataMember attributes) like this:
[DataContract]
public class Cat
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Breed { get; set; }
}
You can do this with JavaScriptSerializer found in the System.Web.Script.Serialization namespace:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Cat c = serializer.Deserialize<Cat>(jsonString);
I have POCO objects with automatic properties and this works just fine.
EDIT: I wrote about JSON Serializers in .NET which compares this serializer with DataContractJsonSerializer.
baretta's answer solved the k__BackingField bloat for me. Just a tiny addendum that you can decorate this class to auto serialize into either XML or JSON in a similar way:
[Serializable, XmlRoot, DataContract]
public class Cat
{
[XmlElement]
[DataMember]
public string Name { get; set; }
[XmlElement]
[DataMember]
public string Breed { get; set; }
}
... and then use a DataContractJsonSerializer or XmlSerializer to prepare it for your endpoint.
I'm assuming you are passing data via a web service. If you are using the WebService class with the ScriptMethod attribute uncommented-out, the web service methods can read JSON natively. They even use the same JavaScriptSerializer that was mentioned above. If you are using WCF I'm a little more fuzzy on the logic.
But make sure your JSON object are returning data for EVERY property in your class. In your error, there is mention of a Breed property that is not in your example.
Also, on the JavaScript side, do to the dynamic nature of JavaScript it is easy to add new properties to your objects. This can sometimes lead to circular references. You should remove any extra data that you might have added (just as you are sending data via the web method, then add it again once you are done).

Get name of XmlElementAttribute after deserialization

I haven't found any information on this, maybe someone could help.
I have an XML (simplified for convenience):
<content>
<field1>value</field1>
<field2>
<field3>value</field3>
</field2>
</content>
I try to deserialize it using such classes:
[XmlRoot("content")]
public class Content
{
[XmlElement]
public List<Item> Fields { get; set; }
}
public class Item
{
[XmlElement]
public List<Item> Fields { get; set; }
[XmlText]
public String Value { get; set; }
}
I have two questions:
Can I get the actual name of the field? Like [XmlName] string name; in the Item class? Or some kind of an attribute for the class itself? It is not possible to set the node name to "field" and add "type" attribute, for some reasons ;-) While the actual class and serialization process is really complicated, I'd prefer not to implement my own serializer.
Can I add a wildcard like [XmlElement("field*")]? I can't test it until I know the answer to the first question, so if there is a better option, I'd love to know it as well.
Thanks.
You can set the name of the matching XMl- Element or Attribute in the Constructor of the Attribute
[XmlAttribute("FieldAsAttribute")]
--> Will Serialize / Deserialize the Property to the Xml Attribute FieldAsAttribute
or
[XmlElement("FieldAsElement")]
--> Will Serialize / Deserialize the Property to the Xml Element FieldAsElement
The only answer here is that it's, unfortunately, not possible.
As a result we have written our own serialization routine.

Categories