serializing/deserializing derived objects using JSON.NET without using JsonProperty? - json.net

I'm using the NewtonSoft JSON.NET library for serializing the following class where DTOBase can hold derived instances.
public class Command
{
public DTOBase CommandDTO { get; set; }
}
Per this article you need to include the JsonProperty attribute so that the derived instances get deserialized properly
public class Command
{
[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
public DTOBase CommandDTO { get; set; }
}
The question is whether there is any other way besides using an attribute to get the same result? I would prefer to not be coupled to the NewtonSoft library and json serialization in particular at the class level. Is there a way to specify some settings on the Serialize/Deserialize methods of the library at all to get the same result?

The TypeNameHandling property can be set on JsonSerializerSettings when you call JsonConvert.SerializeObject(value, settings).
If you only want the name included for derived objects set TypeNameHandling to TypeNameHandling.Auto.

Related

Ignoring implemented interface property for all implementations [duplicate]

I have an interface with a property like this:
public interface IFoo {
// ...
[JsonIgnore]
string SecretProperty { get; }
// ...
}
I want the SecretProperty to be ignored when serializing all implementing classes. But it seems I have to define the JsonIgnore attribute on every implementation of the property. Is there a way to achieve this without having to add the JsonIgnore attribute to every implementation? I didn't find any serializer setting which helped me.
After a bit of searching, I found this question:
How to inherit the attribute from interface to object when serializing it using JSON.NET
I took the code by Jeff Sternal and added JsonIgnoreAttribute detection, so it looks like this:
class InterfaceContractResolver : DefaultContractResolver
{
public InterfaceContractResolver() : this(false) { }
public InterfaceContractResolver(bool shareCache) : base(shareCache) { }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
var interfaces = member.DeclaringType.GetInterfaces();
foreach (var #interface in interfaces)
{
foreach (var interfaceProperty in #interface.GetProperties())
{
// This is weak: among other things, an implementation
// may be deliberately hiding an interface member
if (interfaceProperty.Name == member.Name && interfaceProperty.MemberType == member.MemberType)
{
if (interfaceProperty.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Any())
{
property.Ignored = true;
return property;
}
if (interfaceProperty.GetCustomAttributes(typeof(JsonPropertyAttribute), true).Any())
{
property.Ignored = false;
return property;
}
}
}
}
return property;
}
}
Using this InterfaceContractResolver in my JsonSerializerSettings, all properties which have a JsonIgnoreAttribute in any interface are ignored, too, even if they have a JsonPropertyAttribute (due to the order of the inner if blocks).
In more recent versions of Json.NET, applying [JsonIgnore] to interface properties now just works and successfully prevents them from being serialized for all implementing types, as long as the property is declared on the same class where the interface is declared. A custom contract resolver is no longer required.
For instance, if we define the following types:
public interface IFoo
{
[JsonIgnore]
string SecretProperty { get; set; }
string Include { get; set; }
}
public class Foo : IFoo
{
public string SecretProperty { get; set; }
public string Include { get; set; }
}
Then the following test passes in Json.NET 11 and 12 (and probably earlier versions also):
var root = new Foo
{
SecretProperty = "Ignore Me",
Include = "Include Me",
};
var json = JsonConvert.SerializeObject(root);
Assert.IsTrue(json == "{\"Include\":\"Include Me\"}");// Passes
Demo fiddles here and here.
I believe this was added in Json.NET 4.0.3 despite the fact that JsonIgnore was not mentioned explicitly in the release notes:
New feature - JsonObject and JsonProperty attributes can now be placed on an interface and used when serializing implementing objects.
(The implementation can be found in JsonTypeReflector.GetAttribute<T>(MemberInfo memberInfo).)
However, as noted by Vitaly, this does not work when the property is inherited from a base class of the class where the interface is declared. Demo fiddle here.
I have found it's simplest to create a DTO of only the properties I want and serialize that object to JSON. it creates many small, context specific objects but managing the code base is much easier and I don't have to think about what I'm serializing vs what I'm ignoring.
You should add [DataContract] in front of the class name.
It changes the default from including all properties, to including only explicitly marked properties. After that, add '[DataMember]' in front of each property you want to include in the JSON output.

Specifying serialized names in java class for firestore document

I am trying to store a document in firestore in my android app using a custom object. If I am using proguard for building my app, is there a way to specify the serialized name for the fields inside my class like the way Gson provides using #SerializedName annotation?
You can specify the name a Java property gets in the JSON of the document with the PropertyName annotation. For example:
public class Data {
#PropertyName("some_field_name")
public String someFieldName;
}
If you use getters and setters (instead of using a public field as above), be sure to put the annotation on both getter and setter:
public class Data {
private String someFieldName;
#PropertyName("some_field_name")
public String getSomeFieldName() { return someFieldName; }
#PropertyName("some_field_name")
public void setSomeFieldName(String someFieldName) { this.someFieldName = someFieldName; }
}
This annotation is shared between Cloud Firestore and the older Firebase Realtime Database, so I recommend also checking out some of the previous questions about PropertyName, such as Naming convention with Firebase serialization/deserialization?.

Make an XML element mandatory

Here I am currently working on a program that will serialize an XML file asp.net object. My problem is that I can not find the attribute that makes it mandatory to have a tag in the XML file.
You will find below the definition of my object.
[System.SerializableAttribute()]
public class EchangeIdentification
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("agrement")]
public string Agrement{ get; set; }
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("cvi")]
public string NumeroCvi { get; set; }
/// <remarks/>
[Required]
[XmlElement("siret")]
public string Siret { get; set; }
}
As far as I know, there is no way to declaratively force elements and attributes to be required using the XmlSerializer. C# object properties that can be null are always optional.
A few observations
[Serializable] is not used by the XML Serializer.
There is no way to make it required using the XML Serializer, but if you don't have to use XmlSerializer? DataContractSerializer provides the following option:
[DataMember(IsRequired = true)]
You don't need the "Attribute" name in the code, your code could look like this
[Serializable]
public class EchangeIdentification
{
[XmlElement("agrement")]
public string Agrement{ get; set; }
[XmlElement("cvi")]
public string NumeroCvi { get; set; }
[XmlElement("siret")]
public string Siret { get; set; }
}
Define "serialize an XML file asp.net object" and "makes it mandatory to have a tag in the XML". It all depends on how you're using this class.
Are you using it as a deserialization container, into which you will deserialize XML you receive? Then create an XSD schema, and validate the incoming XML before (or rather during) serialization. See Validating an XML against referenced XSD in C#.
On the other hand, if the user of this code is assigning properties of an instance of this class at runtime, and you serialize it through XmlSerializer, you could validate the output after serializing. See the linked question above, and Can I fail to deserialize with XmlSerializer in C# if an element is not found?.
Alternatively, you could implement serialization callbacks and create a validation method that throws an exception if [Required] properties have the default value for their type.
I'd go with the XSD route either way.

During JSON Serialization in .NET, is there a way to specify how "deep" the object graph you wish to go?

I have some complex object graphs, when I want to send them down to the client, I'm creating a separate DTO and serializing the objects into that. This is a pain in the ass. Is there anyway to serialize objects and only say, "Go one references deep" so if I have an object:
public class Test {
public Project { get; set; }
}
public class Project {
public int Id { get; set; }
public Vendor Vendor { get; set; }
}
If I go to serialize Test it won't go to the Vendor, but it'll correctly serialize the Project. I realize I can add an annotation for JsonIgnore, but if I were serializing all Projects, I might want a Vendor.
I think you're going to have to do some custom extension work: I found a conversation and some samples at http://json.codeplex.com/Thread/View.aspx?ThreadId=24459

ASP.NET MVC, Linq to SQL Data Annotation Validation

I'm trying implement Data Annotation to my Linq to SQL objects. The .dbml file is generated and I'm not sure how to add data annotation to the objects without touching the generated source code.
I tried to add data annotations to the a separate partial class of the object, but its not recognizing it, no Intelli sense either.
As I said in my original answer to this question, you should use an interface. The answer posted after mine (which was marked as Accepted) said to use a class. This is not as good. An interface is a better option for the following reasons:
If there is a mismatch between the name in your LINQ class and the name in your interface, the compiler will flag it for you
An interface can not be instantiated, so this protects class users from accidentally instatntiating the metadata type
If you use Resharper (or similar), the interface can be automatically extracted from the LINQ class
An interface is less verbose than an empty class
If you program against interfaces rather than classes (which is a good practice), then you've already got an interface you can use as your metadata type
For a class called, say "User", create an interface for it (say 'IUser'), and then update the definition of your partial User class as follows:
[MetadataType(typeof(IUser))]
public class User : IUser
Then, in your IUser interface, add appropriate Data Annotation attributes to the properties:
[Required]
[StringLength(50, ErrorMessage = "Username cannot exceed 50 characters")]
string Username { get; set; }
For a class called, say "User", create an interface for it (say 'IUser'), and then update the definition of your partial User class as follows:
[MetadataType(typeof(IUser))]
public class User : IUser
Then, in your IUser interface, add appropriate Data Annotation attributes to the properties:
[Required]
[StringLength(50, ErrorMessage = "Username cannot exceed 50 characters")]
string Username { get; set; }
Linq to SQL generates object classes as partial. An easy way to implement data annotations is to create your own partial class of the object, place the [MetadataType(typeof(YourDataAnnotationClass))] on the partial class you created.
Example:
// Linq to SQL Class
public partial class Article
{
public string Title { get; set; }
...... etc
}
Create your own MetaData class with Metadata for each field you want to validate
public class MyMetaDataClass
{
[Required]
[Range(5,20)]
public string Title { get; set; }
}
Create a Partial Class for the Object class you want to add metadata to, in this case Articles class:
[MetadataType(typeof(MyMetaDataClass))]
public partial class Article { }
Note: you don't need to specify anything in the class, just the metadata type.
Thanks,but the problem is MS define the prototype of MetadataTypeAttrubute as
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class MetadataTypeAttribute : Attribute
So, you had to use class but not interface
From China
Forest Lee: 李晓强
xiaoqianglinsen#163.com (MSN)
lixiaoqiang#webservice.com.cn

Resources