Initialize a Object having multiple Object as Properties - c#

I have a class as
public class Root
{
public Child1 child1 { get; set; }
public Child2 child2 { get; set; }
}
public class Child1
{
public Grandchild grandChild { get; set; }
}
public class Grandchild
{
public string a { get; set; }
}
I am trying to get the output in json as
{
"Child1": {
"Grandchild": {
"a": ""
}
},
"Child2":{...}
}
I am having a constraint of not using a constructor, is there a better way instead of manually initializing each and every class?
Have tried using a contactResolver but from that only till child1 and child2 are getting initializd
{
"Child1": {
"Grandchild": null
},
"Child2":{...}
}
If I serialize new Root() then I will get the json as
{
"Child1" : null,
"Child2": null
}
Is there a way without defining the constructor to get the expected output?

Related

Get access to parent class

I'm fighting with some classes or better objects taht are nested in a "main object".
Example:
public class Parent
{
public string MothersName { get; set; }
public Child child = new Child(){ ChildsName = "Child1"; }
}
public class Child
{
public string ChildsName{ get; set; }
.... Parent MothersName = "LovelyOne";
}
So is there any way to change the mothers name from the child-object?
The child needs to have a reference to the parent class:
public class Parent
{
public string MothersName { get; set; }
public Child child;
public Parent()
{
child = new Child("Child1", this);
}
}
public class Child
{
public string ChildsName { get; set; }
public Parent Parent { get; }
public Child(string childsName, Parent parent)
{
this.ChildsName = childsName;
this.Parent = parent;
}
}
myChild.Parent.MothersName = "LovelyOne"; works now inside of Child.

Is there a way to use list with EF Core Postgres JSON?

This is possible in PG:
public class Parent
{
[Column(TypeName = "jsonb")]
//Mode 1: a column in the table
public Child[] Children { get; set; }
}
public class Child
{
//Mode 2: a virtual column only existing in JSON
public GrandChild[] GrandChildren { get; set; }
}
public class GrandChild
{
}
My question if there is a way to use other CLR types inline, instead of arrays, such as List<T>, HashSet<T> or even just IList<T> or ICollection<T>, to enable easy access and to avoid recreation of the collection each time we want to make a change, or to avoid defining a bunch of other proxy properties.
I tried setting HasConversion to array but it didn't work.
This works "automatically" if you enable the type plugins in Npgsql.Json.NET:
NpgsqlConnection.GlobalTypeMapper.UseJsonNet();
using (var context = new MyContext(options.Options))
{
var parent = new Parent()
{
Children = {
new Child() {
GrandChildren = {
new GrandChild() { Name = "A" },
new GrandChild() { Name = "B" }
}
}
}
};
context.Add(parent);
context.SaveChanges();
foreach(var p in context.Parents.ToList()) {
// This is just to print the whole object. You don't have to touch JSON.NET
// yourself here, Npgsql will convert to/from .net types at 'the edges'.
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(p));
}
}
// Using these definitions
class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options)
: base(options)
{ }
public DbSet<Parent> Parents { get; set; }
}
public class Parent
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column(TypeName = "jsonb")]
public List<Child> Children { get; set; } = new List<Child>();
}
public class Child
{
public List<GrandChild> GrandChildren { get; set; } = new List<GrandChild>();
}
public class GrandChild
{
public string Name { get; set; }
}

Store/retrieve child-parent relationship with JsonConverter

I have a JSON structure (including POCO classes) with child-objects arrays like this:
"Object": [
{
"Name": "TestA",
"ChildObjects": [
{
"Name": "TestB"
"ChildObjects": [
{
"Name": "TestC"
...
}
]
}
]
When deserializing, I would like to keep a reference to the parent
object I've just created.
But I must get this reference before populating the child-object.(On the moment that I populate the child-object I must have the parent-object structure/reference accessible).
I've tried using a custom JsonConverter, but
I could not find a way to store or retrieve this relationship.
Rather than defining this as a serialization problem (how to serialize and deserialize a back-reference to a parent), it might make sense to define this as a class design problem, namely
Given a hierarchy of parents and children, how to ensure that child back-references to parents are automatically set correctly when adding them to their parents?
Once the problem is defined in this way and solved, correctness should be assured both during deserialization and during programmatic data creation, since the parent back-reference would never need to be serialized or deserialized.
One way to accomplish this would be to define a custom subclass of Collection<T> that automatically sets and clears parent back references.
First, define the following interface and collection:
public interface IHasParent<TParent> where TParent : class
{
TParent Parent { get; }
void OnParentChanging(TParent newParent);
}
public class ChildCollection<TParent, TChild> : Collection<TChild>
where TChild : IHasParent<TParent>
where TParent : class
{
readonly TParent parent;
public ChildCollection(TParent parent)
{
this.parent = parent;
}
protected override void ClearItems()
{
foreach (var item in this)
{
if (item != null)
item.OnParentChanging(null);
}
base.ClearItems();
}
protected override void InsertItem(int index, TChild item)
{
if (item != null)
item.OnParentChanging(parent);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
var item = this[index];
if (item != null)
item.OnParentChanging(null);
base.RemoveItem(index);
}
protected override void SetItem(int index, TChild item)
{
var oldItem = this[index];
if (oldItem != null)
oldItem.OnParentChanging(null);
if (item != null)
item.OnParentChanging(parent);
base.SetItem(index, item);
}
}
Then define your MyObject and RootObject types as follows:
public class MyObject : IHasParent<MyObject>
{
readonly ChildCollection<MyObject, MyObject> childObjects;
public MyObject() { this.childObjects = new ChildCollection<MyObject, MyObject>(this); }
public string Name { get; set; }
public IList<MyObject> ChildObjects { get { return childObjects; } }
#region IHasParent<MyObject> Members
[JsonIgnore]
public MyObject Parent { get; private set; }
public void OnParentChanging(MyObject newParent)
{
Parent = newParent;
}
#endregion
// Added to suppress serialization of empty ChildObjects collections to JSON.
public bool ShouldSerializeChildObjects() { return childObjects.Count > 0; }
}
public class RootObject
{
public RootObject() { this.Object = new List<MyObject>(); }
public List<MyObject> Object { get; set; }
}
Notes:
The collection IList<MyObject> ChildObjects in MyObject is get-only. Json.NET (and XmlSerializer for that matter) can successfully deserialize a get-only, pre-allocated collection.
The method ShouldSerializeChildObjects() is optional and prevents serialization of empty ChildObjects [] array values.
Since ObservableCollection<T> is itself a subclass of Collection<T>, you could chose it as the base class for ChildCollection<TParent, TChild> if you require notifications when items are added or removed.
The Parent property is marked with [JsonIgnore] to prevent its serialization.
Sample fiddle including some basic unit tests.
For clearer understanding dbc's answer let me simplify it.
Let's take example of setting parent for RootObject's item called MyObject:
{
"Object":[
{
"Name": "TestA"
}
]
}
Define collection:
public class Items : Collection<MyObject>
{
private RootObject Owner;
public Items(RootObject owner)
{
Owner = owner;
}
protected override void InsertItem(int index, MyObject item)
{
item.Parent = Owner;
base.InsertItem(index, item);
}
}
Define MyObject and RootObject:
public class MyObject
{
[JsonIgnore]
public RootObject Parent { get; set; }
public string Name { get; set; }
}
public class RootObject
{
public RootObject() { ChildObjects = new Items(this); }
public Items ChildObjects { get; }
}
You needn't JsonConverter.
You can create POCO classes that represent your json, as given below:
public class OstacolisRuntime
{
public int CodiceOstacolo { get; set; }
public int TipoOstacolo { get; set; }
public int Tipologia { get; set; }
public string Nome { get; set; }
public double PosizioneX { get; set; }
public double PosizioneY { get; set; }
public double PosizioneZ { get; set; }
public double AngoloX { get; set; }
public double AngoloY { get; set; }
public double AngoloZ { get; set; }
public double ScalaX { get; set; }
public double ScalaY { get; set; }
public double ScalaZ { get; set; }
public List<SubOggetto> SubOggettos { get; set; } //sub
}
public class SubOggetto
{
public string Immagine { get; set; }
public int Tipologia { get; set; }
public string Nome { get; set; }
public double PosizioneX { get; set; }
public double PosizioneY { get; set; }
public double PosizioneZ { get; set; }
public double AngoloX { get; set; }
public double AngoloY { get; set; }
public double AngoloZ { get; set; }
public double ScalaX { get; set; }
public double ScalaY { get; set; }
public double ScalaZ { get; set; }
public List<SubOggetto> SubOggettos { get; set; } //recursive relashioship
}
public class RootObject
{
public List<OstacolisRuntime> OstacolisRuntime { get; set; }
}
Deserialize you json:
var o= JsonConvert.DeserializeObject<RootObject>(json);
You can check complete source code

Json.Net - Deserialize object with "dynamic" properties

I got the following Json data
{
"HasErrors": false,
"Includes": {
"Products": {
"091006": {
"hej" : "tja"
},
"091026": {
"hej" : "tjafsafsa"
}
}
}
}
By dynamic JSON i mean that the propertys on the Products class changes so I cant hardcode them in the c# class in the same way that I do with "HasErrors" for example.
Example:
{
"HasErrors": false,
"Includes": {
"Products": {
"091006": {
"hej" : "tja"
},
"091026": {
"hej" : "tjafsafsa"
}
}
}
}
Another example:
{
"HasErrors": false,
"Includes": {
"Products": {
"091126": { //CHANGED
"hej" : "tja"
},
"091043226": { //CHANGED
"hej" : "tjafsafsa"
}
}
}
}
I've built up the following classes in .NET
Response.cs
public class Response<T> where T : new()
{
[JsonProperty("hasErrors")]
public bool HasErrors { get; set; }
[JsonProperty("includes")]
public Includes<T> Includes { get; set; }
}
Includes.cs
public class Includes<T> where T : new()
{
[JsonProperty("products")]
public ProductRoot Products { get; set; }
}
ProductRoot.cs
public class ProductRoot
{
[JsonProperty("products")]
public Dictionary<string, Product> Products { get; set; }
}
Product.cs
public class Product
{
[JsonProperty("hej")]
public string Hej { get; set; }
}
I then try to Deserialize it like this:
var hej = JsonConvert.DeserializeObject<Response<Product>>(json_from_above_as_string);
And then I get this error:
Could not cast or convert from System.String to www.Models.Externals.Product.
[JsonSerializationException: Error converting value "091006" to type 'www.Models.Externals.Product'. Path 'Includes.ProductsOrder[0]', line 1, position 15173.]
You guys have any idea of what Im doing wrong?
I've instantiated an object of type <Response<Product>> successfully and serialized it to get a feel about what's happening under the hood and, as an example, the JSON I get out of it is as follows:
{
"hasErrors":false,
"includes":{
"products":{
"products":{
"091006":{
"hej":"tja"
}
}
}
}
}
This shows that your JSON simply doesn't marry up with your object model. You can do a couple of things. Either change your JSON format to something like the above, or change your object model to the following:
public class Response<T> where T : new()
{
[JsonProperty("hasErrors")]
public bool HasErrors { get; set; }
[JsonProperty("includes")]
public Includes<T> Includes { get; set; }
}
public class Includes<T> where T : new()
{
[JsonProperty("products")]
public Dictionary<string, T> Products { get; set; }
}
public class Product
{
[JsonProperty("hej")]
public string Hej { get; set; }
}
I solved it by removing the ProductRoot class.
It now looks like this:
public class Response<T> where T : new()
{
[JsonProperty("hasErrors")]
public bool HasErrors { get; set; }
[JsonProperty("includes")]
public Includes<T> Includes { get; set; }
}
public class Includes<T> where T : new()
{
[JsonProperty("products")]
public Dictionary<string, Product>Products { get; set; }
}

C# XML Serialization excluding parent class fields

I have a class like this:
public abstract class Node : Button
{
[XmlIgnoreAttribute()]
private bool isMovable;
public abstract ObjectType Type
{
get;
}
public double X { get; set; }
public double Y { get; set; }
public string Nodename { get; set; }
}
Serialization process:
ObjectXMLSerializer<List<Node>>.Save(main.current_data.Nodes, filename);
The trick happens when I try to serialize it: I don't want its parent's (Button) fields to be serialized, because this gives me serialization errors. So later, I can deserialize this xml to get an array of Nodes created when I read the fields they have.
Can I ignore the serialization of the parent's class somehow?
Thanks.
I'd go with containment instead. And serialize the contained NodeInfo. Node information would be the specific difference from a wpf button, the additional info you want to serialize.
public class ButtonNode : System.Windows.Controls.Button
{
private System.Windows.Controls.Button _button;
public ButtonNode(System.Windows.Controls.Button btn) : base() { this._button = btn; }
public NodeInfo NodeInfo { get; set; }
}
public interface INodeInfo { ObjectType Type { get; } }
[XmlInclude(typeof(ConcreteNodeInfo1))]
public abstract class NodeInfo : INodeInfo
{
public NodeInfo() { }
[XmlIgnore] private bool isMovable;
public abstract ObjectType Type { get; }
public double X { get; set; }
public double Y { get; set; }
public string NodeName { get; set; }
}
public class ConcreteNodeInfo1 : NodeInfo
{
public ConcreteNodeInfo1() : base () { }
public override ObjectType Type { get { return ObjectType.ObjectType1; }
}
As a side note, this post tackles the 'why shouldn't I use generics with XmlSerializer'.

Categories

Resources