For look up tables with 1:1 relationships, LinqPad generates a property that points back to the collection of objects that use the lookup value. How to disable this?
It's causing problems when I try to serialize tables using Newtonsoft.JSON.
You can't prevent LINQPad from generating these properties, but you can tell Newtonsoft not to serialize them, with IContractResolver:
http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size
Write your contract resolver class in the My Extensions query, so it will be available to all queries. In the CreateProperties method, where you filter the properties, you'll need to apply a condition on the property type to exclude navigation properties. The following will exclude all n:1 and 1:1 properties:
public class FlatResolver : DefaultContractResolver
{
public static JsonSerializerSettings Settings =
new JsonSerializerSettings { ContractResolver = new FlatResolver() };
protected override IList<JsonProperty> CreateProperties (Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties (type, memberSerialization);
properties = properties
.Where (p => !p.PropertyType.GetCustomAttributes (typeof (System.Data.Linq.Mapping.TableAttribute)).Any())
.ToList();
return properties;
}
}
And then to serialize, just do this:
JsonConvert.SerializeObject (myObject, FlatResolver.Settings).Dump();
You can use similar logic to exclude 1:n, by checking for an IEnumerable of an entity type.
Related
I am try to make conditional serialization base on rules that I give the moment I make the Serialization.
I know that I can use the ShouldSerialize+Name
[ProtoContract]
public class SomeType {
[ProtoMember(1)]
public string Name {get;set;}
private bool ShouldSerializeName() {
// return true to serialize Name, false otherwise
}
}
But what I need is like this example on Newtonsoft.Json.JsonConvert where I give the settings for what i am going to serialize the moment of serialization.
var oResolFilter = new ShouldSerializeContractResolver();
var settings = new JsonSerializerSettings { ContractResolver = oResolFilter };
var Results = JsonConvert.SerializeObject(this, settings);
and
class ShouldSerializeContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = true ; // ( or false)
return property;
}
}
So the question is - how can I do something similar as the JsonConvert on ProtoBuf-Net
reference
I look on most of answers, and on the examples and the source code on protobuf-net but fail to locate a similar solution... here are few questions that I look.
.net serialization: how to selectively ignore data fields
Conditional serialization with protobuf-net
Protobuf-net serialization of object (generic) throws error No serializer defined for type: System.Object
How to ignore default values while serializing json with Newtonsoft.Json
json.net example:
Newtonsoft JSON ShouldSerialize and inheritance
We are running into a situation on an MVC3 project with both the Microsoft JSON serializers and JSON.NET.
Everybody knows DateTime's are basically broken in Microsoft's serializers, so we switched to JSON.NET to avoid this issue. That works great, except that some of the classes we are trying to serialize are POCOs with DataContract/DataMember attributes. They are defined in an assembly that is referenced in multiple places. Additionally, they have some other display properties that are not marked as DataMembers for efficiency. For instance, a Customer
[DataContract]
public class Customer
{
[DataMember]
public string FirstName { get; set;}
[DataMember]
public string LastName { get; set;}
public string FullName
{
get
{ return FirstName + " " + LastName; }
}
}
When this customer is passed over WCF the client side can reference that assembly and use the FullName just fine, but when serialized with JSON.NET it sees that FullName isn't a [DataMember] and doesn't serialize it. Is there an option to pass to JSON.NET to tell it to ignore the fact that a class has [DataContract] attribute applied?
Note:
Using the JavaScriptSerializer in .NET works fine for the FullName property, but DateTimes are broken. I need JSON.NET to ignore the fact that this class has DataContract/DataMember attributes and just do standard public field serialization like it would if they weren't there.
Simply use Json.Net's OptOut attribute. It will take precedence over DataContract.
[DataContract]
[JsonObject(MemberSerialization.OptOut)]
As Amry said you can uses your own IContractResolver.
Unfortunately the solution provided by Amry didn't work for me, below is the solution that I managed to get working:
public class AllPropertiesResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
//property.HasMemberAttribute = true;
property.Ignored = false;
//property.ShouldSerialize = instance =>
//{
// return true;
//};
return property;
}
}
There are a few lines commented, these wern't required to make my solution work, but you never know!
This has the same usage as Amry's solution:
var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings {
ContractResolver = new AllPropertiesResolver()
});
Hope this helps!
I was having a problem almost related to what you're having, and managed to find a solution by going through Json.NET's codes. So it may not be the best solution, but it works for me.
To do this, you need to implement your own IContractResolver. An over-simplified implementation of that to include all parameters and ignores all attributes (not just DataContract but other built-in Json.NET's rules as well, so whatever options you set that should originally affect the members selection is now being overidden by this code):
class AllPropertiesResolver : DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
return objectType.GetProperties()
.Where(p => p.GetIndexParameters().Length == 0)
.Cast<MemberInfo>()
.ToList();
}
}
And here comes the code usage example:
var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings {
ContractResolver = new AllPropertiesResolver()
});
In accordance to the Json.NET documentation [DataMember] attributes are ignored if the properties are also annotated with Json.NET specific attributes (such as [JsonProperty]).See the Serialization Attributes documentation for details:
Json.NET attributes take presidence over standard .NET serialization attributes, e.g. if both JsonPropertyAttribute and DataMemberAttribute are present on a property and both customize the name, the name from JsonPropertyAttribute will be used.
The documentation only covers the name property, but for my experience the [JsonProperty] attribute also fully shadows settings done by the [DataMember] attribute. So, if it is feasible for your case, also add Json.NET attributes to the properties for which the [DataMember] annotation should be ignored.
If you want to ignore the presence of DataContractAttribute for all types without having to add additional attributes, then a custom contract resolver is the correct solution. However, as of Json.NET 9.0.1 Amry's resolver no longer works. Doolali's resolver works but it has the additional side effect of serializing all public properties including those marked with [JsonIgnore]. If you require a contract resolver that only ignores the presence of DataContractAttribute but otherwise behaves like the default contract resolver, the following can be used:
public class IgnoreDataContractContractResolver : DefaultContractResolver
{
static MemberSerialization RemoveDataContractAttributeMemberSerialization(Type type, MemberSerialization memberSerialization)
{
if (memberSerialization == MemberSerialization.OptIn)
{
type = Nullable.GetUnderlyingType(type) ?? type;
// Json.NET interprets DataContractAttribute as inherited despite the fact it is marked with Inherited = false
// https://json.codeplex.com/discussions/357850
// https://stackoverflow.com/questions/8555089/datacontract-and-inheritance
// https://github.com/JamesNK/Newtonsoft.Json/issues/603
// Thus we need to manually climb the type hierarchy to see if one is present.
var dataContractAttribute = type.BaseTypesAndSelf().Select(t => t.GetCustomAttribute<DataContractAttribute>()).FirstOrDefault(a => a != null);
var jsonObjectAttribute = type.GetCustomAttribute<JsonObjectAttribute>();
if (dataContractAttribute != null && jsonObjectAttribute == null)
memberSerialization = MemberSerialization.OptOut;
}
return memberSerialization;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, RemoveDataContractAttributeMemberSerialization(type, memberSerialization));
return properties;
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
contract.MemberSerialization = RemoveDataContractAttributeMemberSerialization(objectType, contract.MemberSerialization);
return contract;
}
}
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
You may want to cache the contract resolver for best performance.
Have you tried this?
IgnoreDataMemberAttribute
I have a bunch of classes that I do not have control over that were created before nullable types. The convention used in these classes is like the following:
Id
IdSpecified = false
In other words, for a given non-nullable property named "Abc", there is a separate boolean property called "AbcSpecified" which indicates whether the first property has a value.
Is there a way to treat the non-nullable properties as nullable and exclude all properties ending in Specified during serialization and deserialization? I am hoping I can do this generically, as there are more than 100 classes like this.
I was able to come up with a generic solution for this using a custom IContractResolver in conjunction with an IValueProvider. The contract resolver is responsible for identifying the pairs of properties "Xyz" and "XyzSpecified" on each class (I'll call these the "target" and "indicator" properties, respectively), and for each pair making sure the indicator property is excluded, while also attaching a value provider instance to the target property. The value provider, in turn, handles the decision of what gets read or written for each object instance. On serialization, it only writes out the target property if the indicator property is set to true. Conversely, on deserialization, it sets the indicator property based on the presence or absence of a value in the JSON, but it only sets the target property on the object if a value is present.
Here is the code for the custom resolver and value provider:
public class CustomResolver : DefaultContractResolver
{
const string IndicatorKeyword = "Specified";
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
Dictionary<string, JsonProperty> dict = props.ToDictionary(p => p.UnderlyingName);
foreach (JsonProperty prop in props)
{
string name = prop.UnderlyingName;
if (name.Length > IndicatorKeyword.Length && name.EndsWith(IndicatorKeyword))
{
// We have an indicator property; ignore it for serialization purposes
prop.Ignored = true;
// Find the corresponding target property, e.g. "XyzSpecified" => "Xyz"
string targetName = name.Substring(0, name.Length - IndicatorKeyword.Length);
JsonProperty coProp = null;
if (dict.TryGetValue(targetName, out coProp))
{
// Create a value provider for the property pointing to the
// "real" target and indicator properties from the containing type
PropertyInfo realTarget = type.GetProperty(targetName);
PropertyInfo realIndicator = type.GetProperty(name);
coProp.ValueProvider = new CustomValueProvider(realTarget, realIndicator);
}
}
}
return props;
}
class CustomValueProvider : IValueProvider
{
PropertyInfo targetProperty;
PropertyInfo indicatorProperty;
public CustomValueProvider(PropertyInfo targetProperty, PropertyInfo indicatorProperty)
{
this.targetProperty = targetProperty;
this.indicatorProperty = indicatorProperty;
}
// GetValue is called by Json.Net during serialization.
// The target parameter has the object from which to read the value;
// the return value is what gets written to the JSON
public object GetValue(object target)
{
bool isSpecified = (bool)indicatorProperty.GetValue(target);
return isSpecified ? targetProperty.GetValue(target) : null;
}
// SetValue gets called by Json.Net during deserialization.
// The value parameter has the value read from the JSON;
// target is the object on which to set the value.
public void SetValue(object target, object value)
{
bool isSpecified = value != null;
indicatorProperty.SetValue(target, isSpecified);
if (isSpecified) targetProperty.SetValue(target, value);
}
}
}
To use the resolver, create a new JsonSerializerSettings instance, then set the ContractResolver property to a new instance of the resolver. Pass the settings to the JsonConvert.SerializeObject() or DeserializeObject() methods and everything should just work.
Here is a full round-trip demo: https://dotnetfiddle.net/i39c8d
Is there way to serialize private fields and autoproperties of an object?
The restriction is that I can't edit classes that i need to serialize which means:
1. I can't add any atributes on members (kinda datacontract)
2. I can't inherit it from an interface (kinda Ixmlserializable )
4. Add getter and setter properties for the fields
3. Class of the root object that i need to serialize is not even marked as serializable
Thanks
You may be able to do something like this (you'll have to get more creative if you have things like collections or non-serializable fields, but you get the idea):
var dict = new Dictionary<string, object>();
foreach (var field in typeof(Foo).GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
{
dict[field.Name] = field.GetValue(f);
}
string json = JsonConvert.SerializeObject(dict);
Basically you're ripping the fields out one at a time, dumping them into a dictionary, then serializing the dictionary.
If you don't want to work with reflection yourself, you can read this article with a list of solutions for serialization.
You can override the DefaultContractResolver to do (de)serialization of only fields without having to decorate the classes:
public class FieldsOnlyContractResolver: DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
return objectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Cast<MemberInfo>().ToList();
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
return base.CreateProperty(member, MemberSerialization.Fields);
}
}
Then, to use it, specify inside JsonConvert.(De)SerializeObject:
var jsonSettings = new JsonSerializerSettings() {
ContractResolver = new FieldsOnlyContractResolver()
};
var json = JsonConvert.SerializeObject(obj, jsonSettings);
var objAgain = JsonConvert.DeserializeObject<ObjType>(json, jsonSettings);
How can I customize Json.NET to serialize private members and NOT serialize public readonly properties (without using attributes).
I've had a stab around at creating a custom IContractResolver but am a bit lost.
For a partial answer, messing with DefaultContractResolver.DefaultMembersSearchFlags can get it to include private things:
Newtonsoft.Json.JsonSerializerSettings jss = new Newtonsoft.Json.JsonSerializerSettings();
if (includePrivateMembers)
{
Newtonsoft.Json.Serialization.DefaultContractResolver dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
jss.ContractResolver = dcr;
}
return Newtonsoft.Json.JsonConvert.SerializeObject(o, jss);
Seems to work on a lot of objects, though with some this seems to generate a CLR exception.
In response to Chris' answer, the DefaultMemberSearchFlags property on DefaultContractResolver was deprecated as of version 6. Despite of what the deprecation message says, I believe you'll need to overwrite the CreateProperties method, too, like L.B explains.
This method gives you full control, including excluding readonly properties:
class PrivateContractResolver : DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
MemberInfo[] fields = objectType.GetFields(flags);
return fields
.Concat(objectType.GetProperties(flags).Where(propInfo => propInfo.CanWrite))
.ToList();
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, MemberSerialization.Fields);
}
}