How to serialize top level objects with Json.NET as objects and nested objects as references - serialization

I want to be able to serialize an object fully if it is at the top level of the serialization context but serialize objects lower in the context by reference.
I've searched and tried tests with Custom Contract Resolvers, Custom Json Converters and custom IReferenceResolver but I can't find a way to do this.
For example, imagine an IdType class that at the top level I want to serialize with all its properties but where I come across a reference to such an object in a property or list or dictionary I want to produce a reference.
For this type and test
public class IdType
{
public IdType(string id)
{
Id = id;
}
public string Id {get;}
public string Name {get;set;}
public int Number {get; set;}
public IdType OtherType { get; set; }
public IEnumerable<IdType> Types { get; set;}
public IDictionary<IdType, string> { get; set; }
public IDictionary<string, IdType> {get; set; }
}
[TestMethod]
public void SerializeTest()
{
var t1 = new IdType(1) { Name = 'Alice', Number = 42 };
var t2 = new IdType(2) { Name = 'Bob', Number = 21, OtherType = t1 };
var t3 = new IdType(2) { Name = 'Charlie', Number = 84, OtherType = t2, Types = new[] {t1, t2} };
var testTypes = new[]
{
t1,
t3
};
var serializer = new JsonSerializer
{
Formatting = Formatting.Indented,
};
StringWriter writer;
using (writer = new StringWriter())
{
serializer.Serialize(writer, myObject);
}
Console.WriteLine(writer.ToString());
}
I want output like this
[
{
"Id": "1",
"Name": "Alice"
"Number": 42,
},
{
"Id": "3",
"Name": "Charlie"
"Number": 84,
"OtherType": 2
"Types": [
"Id" : 1, 2
]
}
]
A JsonConverter has no context so it'll either always convert one way or another.
A custom resolver (derived from DefaultContractResolver) will work for a property of type IdType but I can't work out how to make it work with lists and dictionaries.
Latterly I've tried using PreserveReferenceHandling and a custom IReferenceResolver that has the IDs of the top level elements. But this doesn't work because the serialization is depth first.
Any suggestions to achieve this would be gratefully received

I think I've answered my own question. If I use a combination of a custom contract resolver and a custom converter and conditionally add the converter to the properties I want to serialize to IDs then it seems to work.
I've not implemented dictionaries yet but this works for basic properties and lists:
public class CustomResolver : DefaultContractResolver
{
readonly CamelCasePropertyNamesContractResolver innerResolver = new CamelCasePropertyNamesContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var jsonProperty = base.CreateProperty(member, memberSerialization);
if (!jsonProperty.PropertyType.IsPrimitive && jsonProperty.PropertyType != typeof(string) && jsonProperty.Readable)
{
var innerContract = innerResolver.ResolveContract(jsonProperty.PropertyType);
if (typeof(IdType).IsAssignableFrom(innerContract.UnderlyingType) && innerContract is JsonObjectContract objectContract)
{
jsonProperty.Converter = new IdConverter();
}
else if (typeof(IEnumerable<IdType>).IsAssignableFrom(innerContract.UnderlyingType) && innerContract is JsonArrayContract arrayContract)
{
jsonProperty.Converter = new IdConverter();
}
}
return jsonProperty;
}
}
internal class IdConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (typeof(IdType).IsAssignableFrom(objectType) ||
typeof(IEnumerable<IdType>).IsAssignableFrom(objectType));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is IdType item)
{
JToken token = JToken.FromObject(item.Id);
token.WriteTo(writer);
}
else if (value is IEnumerable<IdType> itemCollection)
{
JArray array = new JArray();
foreach (var i in itemCollection)
{
JToken token = JToken.FromObject(i.Id);
array.Add(token);
}
array.WriteTo(writer);
}
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
To serialize and making use of the custom resolver you would:
var serializer = new JsonSerializer
{
Formatting = Formatting.Indented,
ContractResolver = new CustomResolver(),
};

Related

JsonConverterAttribute is not working for Deserialization in ASP.NET Core 3.1 / 5.0

I want set property names at runtime. I already achieve this for serialization.
For example. I have a simple model like as below:
[JsonConverter(typeof(DataModelConverter))]
public class DataModel
{
public string Name { get; set; }
public int Age { get; set; }
}
And I have a simple DataModelConverter, that inherited from JsonConverter:
public class DataModelConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type type = value.GetType();
JObject jo = new JObject();
foreach (PropertyInfo prop in type.GetProperties())
{
jo.Add(prop.Name == "Name" ? "FullName" : prop.Name, new JValue(prop.GetValue(value)));
}
jo.WriteTo(writer);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DataModel);
}
}
And I have a simple controller like as below:
[Route("api/[controller]")]
[ApiController]
public class NewtonController : ControllerBase
{
public IEnumerable<DataModel> GetNewtonDatas([FromBody] DataModel input)
{
return new List<DataModel>()
{
new DataModel
{
Name="Ramil",
Age=25
},
new DataModel
{
Name="Yusif",
Age=26
}
};
}
}
If I call this API, result will like as below (Showing FullName Instead of Name):
[
{
"FullName": "Ramil",
"Age": 25
},
{
"FullName": "Yusif",
"Age": 26
}
]
But I have a problem. This is not working for deserialization.
For example: If I call this API with this body, then Name will null.
{
"FullName":"Ramil"
}
My attribute is not working for deserialization. I want set property name via attribute for deserialization at runtime .
I don't want use some middleware, I want to achieve this only by using the any attribute at runtime. I must read JSON property names from my appsettings.json file.
Thanks for help!
You have overridden CanRead to return false:
public override bool CanRead
{
get { return false; }
}
This causes Json.NET not to call your your converter's DataModelConverter.ReadJson() method during deserialization, and instead use default deserialization. Since "FullName" does not have the same (case-invariant) name as the Name property, it never gets set, and remains null.
To fix this, remove the override for CanRead (the default implementation returns true) and implement ReadJson(), e.g. as follows:
public class DataModelConverter : NameRemappingConverterBase
{
static string AlternateName => "FullName";
static string OriginalName => "Name";
public override bool CanConvert(Type objectType) => objectType == typeof(DataModel);
// Replace the below logic with name mappings from appsettings.json
protected override string ToJsonPropertyName(JsonProperty property) =>
string.Equals(property.UnderlyingName, OriginalName, StringComparison.OrdinalIgnoreCase) ? AlternateName : base.ToJsonPropertyName(property);
protected override string FromJsonPropertyName(string name) =>
string.Equals(name, AlternateName, StringComparison.OrdinalIgnoreCase) ? OriginalName : base.FromJsonPropertyName(name);
}
public abstract class NameRemappingConverterBase : JsonConverter
{
protected virtual string ToJsonPropertyName(JsonProperty property) => property.PropertyName;
protected virtual string FromJsonPropertyName(string name) => name;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
if (reader.TokenType != JsonToken.StartObject)
throw new JsonSerializationException(string.Format("Unexpected token {0}", reader.TokenType));
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
var value = existingValue ?? contract.DefaultCreator();
while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndObject)
{
if (reader.TokenType != JsonToken.PropertyName)
throw new JsonSerializationException(string.Format("Unexpected token {0}", reader.TokenType));
var name = FromJsonPropertyName((string)reader.Value);
reader.ReadToContentAndAssert();
var property = contract.Properties.GetProperty(name, StringComparison.OrdinalIgnoreCase);
if (!ShouldDeserialize(property))
{
reader.Skip();
}
else
{
var propertyValue = serializer.Deserialize(reader, property.PropertyType);
property.ValueProvider.SetValue(value, propertyValue);
}
}
return value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(value.GetType());
writer.WriteStartObject();
foreach (var property in contract.Properties.Where(p => ShouldSerialize(p, value)))
{
var propertyValue = property.ValueProvider.GetValue(value);
if (propertyValue == null && serializer.NullValueHandling == NullValueHandling.Ignore)
continue;
var name = ToJsonPropertyName(property);
writer.WritePropertyName(name);
serializer.Serialize(writer, propertyValue);
}
writer.WriteEndObject();
}
protected virtual bool ShouldDeserialize(JsonProperty property) =>
property != null && property.Writable;
protected virtual bool ShouldSerialize(JsonProperty property, object value) =>
property.Readable && !property.Ignored && (property.ShouldSerialize == null || property.ShouldSerialize(value));
}
public static partial class JsonExtensions
{
public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
reader.ReadAndAssert().MoveToContentAndAssert();
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
}
Demo fiddle here.

Newtonsoft Json.NET Ignore a member at runtime in Json converter or invoking JsonConverter SerializeObject

Let's say I have the following custom JsonConverter for serialization and/or deserialization:
public class VersionConverter : JsonConverter<Version>
{
public override void WriteJson(JsonWriter writer, Version value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override Version ReadJson(JsonReader reader, Type objectType, Version existingValue, bool hasExistingValue, JsonSerializer serializer)
{
string s = (string)reader.Value;
return new Version(s);
}
}
public class NuGetPackage
{
public string PackageId { get; set; }
public Version Version { get; set; }
public string Description { get; set; }
}
Let's say I have the following code snippet in my application:
NuGetPackage p1 = new NuGetPackage
{
PackageId = "Newtonsoft.Json",
Version = new Version(10, 0, 4),
Description = null
};
string json = JsonConvert.SerializeObject(p1, Formatting.Indented, new VersionConverter());
I want the Json.NET converter to Ignore the Description member variable of the NuGetPackage class.
Note: I do Not Want to use the following "marker boolean" member variable:
public bool ShouldSerializeINSERT_YOUR_PROPERTY_NAME_HERE()
{
if(someCondition){
return true;
}else{
return false;
}
}
I would rather specify the ignoring of a specific member variable somewhere
a) when my code invokes the JsonConvert.SerializeObject?
b) or within the VersionConverter code class itself?
Could someone please show me how to ignore the specific member variable in such a way?
Since NuGetPackage is fairly simple, you could just write an additional JsonConverter for NuGetPackage that serializes only the members you need, e.g.:
public class SimplifiedNuGetPackageConverter : JsonConverter
{
public override bool CanConvert(Type objectType) { return objectType == typeof(NuGetPackage); }
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var package = (NuGetPackage)value;
serializer.Serialize(writer, new { package.PackageId, package.Version });
}
}
Then serialize as follows:
var settings = new JsonSerializerSettings
{
Converters = { new VersionConverter() },
};
if (!someCondition)
settings.Converters.Add(new SimplifiedNuGetPackageConverter());
var json = JsonConvert.SerializeObject(p1, Formatting.Indented, settings);
If you are serializing multiple instances of NuGetPackage at once and need to write Description for some but not all, you could add the logic for someCondition inside WriteJson() itself:
public class ConditionalNuGetPackageConverter : JsonConverter
{
public override bool CanConvert(Type objectType) { return objectType == typeof(NuGetPackage); }
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var package = (NuGetPackage)value;
// Replace with your logic:
var someCondition = !string.IsNullOrWhiteSpace(package.Description);
if (someCondition)
serializer.Serialize(writer, new { package.PackageId, package.Version, package.Description });
else
serializer.Serialize(writer, new { package.PackageId, package.Version });
}
}
And then serialize as follows:
var settings = new JsonSerializerSettings
{
Converters = { new ConditionalNuGetPackageConverter(), new VersionConverter() },
};
var json = JsonConvert.SerializeObject(p1, Formatting.Indented, settings);
Working .Net fiddle here.

JSON.NET strongly typed object inheriting from DynamicObject deserialization/serialization

C#
Given:
[JsonObject(MemberSerialization.OptOut)]
public class Customer : DynamicObject{
public string FirstName { get; set; }
public string LastName { get; set; }
}
JavaScript:
var customer = {
FirstName: "John",
LastName: "Doe",
DOB: "12/18/1984"
};
Is there a a setting in JSON.NET or something else that has to happen such that the DOB would be deserialized to strongly typed Customer when json is posted to server?
to get this to work use custom converter overriding the ReadJson, and WriteJson methods
public class CustomConverter : JsonConverter{
public override void WriteJson(JsonWriter writer,
object value,
JsonSerializer serializer)
{
if (value is DynamicSword)
{
var ds = (DynamicSword)value;
string[] serializable;
string[] notSerializable;
ds.SetSerializableAndNotSerializable(out serializable, out notSerializable);
var jobject = new JObject();
foreach (var item in serializable)
{
var tempValue = ds[item];
if (tempValue != null)
{
jobject.Add(item, JToken.FromObject(tempValue));
}
}
jobject.WriteTo(writer);
}
else
{
JToken t = JToken.FromObject(value);
t.WriteTo(writer);
}
}
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
ConstructorInfo magicConstructor = objectType.GetConstructor(Type.EmptyTypes);
var newObject = magicConstructor.Invoke(new object[]{});
JObject jObject = JObject.Load(reader);
if (newObject is DynamicSword)
{
var ds = (DynamicSword)newObject;
hydrate(jObject, ds);
}
else
{
//do something different?
//really shoulnt be in here anyways
}
return newObject;
}
....
}

Serializing object graph using MongoDB Bson serializer

I've been playing a little with the MongoDB Bson serializer, using the following piece of code:
class Program
{
public class myValue
{
public int Id = 0;
public string Label = "";
}
public class myValueMap : Dictionary<string, myValue>
{
}
public class myProdData
{
public myValueMap Mapping { get; set; }
}
public class mySystemPosition
{
public string Text { get; set; }
public myProdData ProdData { get; set; }
}
static void Main(string[] args)
{
BsonClassMap.RegisterClassMap<mySystemPosition>();
BsonClassMap.RegisterClassMap<myProdData>();
BsonClassMap.RegisterClassMap<myValueMap>();
BsonClassMap.RegisterClassMap<myValue>();
var o = new mySystemPosition()
{
ProdData = new myProdData()
{
Mapping = new myValueMap()
{
{"123", new myValue() {Id = 1, Label = "Item1"}},
{"345", new myValue() {Id = 2, Label = "Item2"}},
}
}
};
var bson = o.ToBson();
var text = Encoding.ASCII.GetString(bson);
}
}
however I don't seem to be able to get the myProdData.Mapping serialized....
Do I need to configure the MongoDB Bson serializer in a special way, to make this work?
You no need to use BsonClassMap.RegisterClassMap if you no need custom serializtion(documentation).
All your classes will be desirialzied according to default rules.
Also i am changed your example a little bit to get it work(i've replaces myValueMap class with Dictionary):
public class myProdData
{
public Dictionary<string, myValue> Mapping { get; set; }
}
static void Main(string[] args)
{
var o = new mySystemPosition()
{
ProdData = new myProdData()
{
Mapping = new Dictionary<string, myValue>()
{
{"123", new myValue() {Id = 1, Label = "Item1"}},
{"345", new myValue() {Id = 2, Label = "Item2"}},
}
}
};
var json = o.ToJson();
Console.WriteLine(json);
Console.ReadKey();
}
Here is console output(just well formatted):
{
"Text":null,
"ProdData":{
"Mapping":{
"123":{
"_id":1,
"Label":"Item1"
},
"345":{
"_id":2,
"Label":"Item2"
}
}
}
}
You can test your serializtion using ToJson() extention method, in order to view that all correct and after that use ToBson() if need.
The problem is that myValueMap derives from Dictionary. That results in a class that the AutoMap method can't handle.
I recommend you just use the Dictionary directly, as Andrew did in his reply.
Ufortunately the myValueMap is an object that I can't easily change, however it turns out, that's pretty easy to create your own (de)serializer....
public class myValueMapSerializer : IBsonSerializer
{
public object Deserialize(Bson.IO.BsonReader bsonReader, System.Type nominalType, System.Type actualType, IBsonSerializationOptions options)
{
if (nominalType != typeof(myValueMap)) throw new ArgumentException("Cannot serialize anything but myValueMap");
var res = new myValueMap();
var ser = new DictionarySerializer<string, myValue>();
var dic = (Dictionary<string, myValue>)ser.Deserialize(bsonReader, typeof(Dictionary<string, myValue>), options);
foreach (var item in dic)
{
res.Add(item.Key, item.Value);
}
return res;
}
public object Deserialize(Bson.IO.BsonReader bsonReader, System.Type nominalType, IBsonSerializationOptions options)
{
throw new Exception("Not implemented");
}
public bool GetDocumentId(object document, out object id, out IIdGenerator idGenerator)
{
id = null;
idGenerator = null;
return false;
}
public void Serialize(Bson.IO.BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
if (nominalType != typeof(myValueMap)) throw new ArgumentException("Cannot serialize anything but myValueMap");
var ser = new DictionarySerializer<string, myValue>();
ser.Serialize(bsonWriter, typeof(DictionarySerializer<string, myValue>), value, options);
}
public void SetDocumentId(object document, object id)
{
return;
}
}

Can Json.NET deserialize a flattened JSON string with dot notation?

I have a flattened JSON:
{
"CaseName" : "John Doe v. State",
"CaseDate" : "<some date>",
"Client.FirstName" : "John",
"Client.LastName" : "Doe",
"Client.Email" : "johndoe#gmail.com"
etc...
}
I want to deserialize it back to this entity:
public class Case()
{
public string CaseName { get; set; }
public string CaseDate { get; set; }
public Client Client { get; set; }
}
where Client.FirstName, Client.LastName, and Client.Email are properties in the Client object. Using Json.NET, is there any way to get it to parse the dot notation and deserialize this entity correctly? Currently, using the default settings, it tells me that Client.FirstName is not a property in type Case.
Yes, you can. You would derive a class from JsonConverter and override the CanConvert method to indicae that you can convert the Client type.
Then, you would override the ReadJson and WriteJson methods to read and write the fields of the JSON literal.
For a JSON literal like this, it's more than likely you will need to create a JsonConverter for the Case type, as you will need to cache all the properties of the Client object during serialization until you have enough information to actually create the Client instance.
Then, you would call the Add method on the JsonConverterCollection instance exposed by the Converters property on the JsonSerializer instance you are using to perform your serialization/deserialization.
Note that if you need to do this for a number of different classes that might be represented in this manner, then you can write one JsonConverter implementation, and have it scan for an attribute on the property. If the property has the attribute and exposes another object with properties, it would expect to read/write the dot-notation.
It should be noted that while you are using the dot-notation for the identifier, it's very uncommon to do so. If possible, on the side that is constructing the JSON literal, it should be doing it in this manner:
{
CaseName: "John Doe v. State",
CaseDate: "<some date>",
Client:
{
FirstName: "John",
LastName: "Doe",
Email: "johndoe#gmail.com"
}
}
But that's assuming that you have control over that end. If you don't, then there's not much you can do.
If you do have control, then constructing your JSON literals in that manner would negate the need for a custom JsonConverter implementation.
simple code
public class SimpleDotJsonPropertyConverter : JsonConverter
{
public const string SplitChar = ".";
private readonly NamingStrategy _namingStrategy;
public SimpleDotJsonPropertyConverter() : this(new DefaultNamingStrategy())
{
}
public SimpleDotJsonPropertyConverter(Type namingStrategyType) : this(namingStrategyType.CreateInstance() as NamingStrategy)
{
}
public SimpleDotJsonPropertyConverter(NamingStrategy namingStrategy)
{
_namingStrategy = namingStrategy;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteRaw("{}");
return;
}
writer.WriteStartObject();
var type = value.GetType();
var props = type.GetPublicProperties();
foreach (var p in props)
{
if (p.PropertyType.IsValueType || p.PropertyType == typeof(string))
{
writer.WritePropertyName(_namingStrategy.GetPropertyName(p.Name, false));
writer.WriteValue(p.GetValue(value));
}
else
{
var parentName = p.Name;
var subProps = p.PropertyType.GetPublicProperties();
var memberValue = p.GetValue(value);
foreach (var sp in subProps)
{
writer.WritePropertyName(_namingStrategy.GetPropertyName(parentName, false) + SplitChar + _namingStrategy.GetPropertyName(sp.Name, false));
writer.WriteValue(sp.GetValue(memberValue));
}
}
}
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
var jsonObject = JObject.Load(reader);
var result = objectType.CreateInstance();
foreach (var item in jsonObject)
{
if (item.Key.IsNullOrEmpty()) continue;
var nameArrays = item.Key.Split(SplitChar, StringSplitOptions.RemoveEmptyEntries);
if (nameArrays.Length <= 1)
{
var p = objectType.GetProperty(item.Key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (p != null)
{
if (item.Value == null)
p.SetValue(result, objectType.GetDefaultValue());
else
p.SetValue(result, item.Value.ToObject(p.PropertyType));
}
}
else
{
var name = nameArrays[0];
var subName = nameArrays[1];
var p = objectType.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (p == null) continue;
var subProp = p.PropertyType.GetProperty(subName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (subProp == null) continue;
if (!subProp.PropertyType.IsValueType && subProp.PropertyType != typeof(string)) throw new NotSupportedException("Nested complex objects are not supported ");
var member = p.GetValue(result);
if (member == null)
{
member = p.PropertyType.CreateInstance();
p.SetValue(result, member);
}
if (item.Value == null)
subProp.SetValue(member, objectType.GetDefaultValue());
else
subProp.SetValue(member, item.Value.ToObject(subProp.PropertyType));
}
}
return result;
}
public override bool CanConvert(Type objectType) => objectType.IsClass;
}
Although only half the problem (i.e. not helping with the fact your object has been flattened)
You can deal with dot notation in a very quick and dirty way with a simple
MyTargetClass retVal
= JsonConvert.DeserializeObject<MyTargetClass>(jsonAsString.Replace(".", "_"));
In combo with appropriate "_" property names on the MyTargetClass e.g.
public class MyTargetClass
{
public string CaseName {get; set;}
public DateTime CaseDate {get; set;}
public string Client_FirstName {get; set;}
//Other Properties
}