How to ignore ObjectSchema and Ream properties when serializing a realmObject - c#

I m trying to serialize a RealmObject in my uwp project and I would like to know if there is any way to to ignore ObjectSchema and Ream properties when serializing a realmObject ? I tried to create a constuctor to avoid copying these two properties but It doesn't worked for me.
This is my object :
public class Sector : RealmObject, NodeBase
{
[PrimaryKey]
public int id { get; set; }
public string key { get; set; }
[Ignored]
public Dictionary<string, string> title { get; set; }
[JsonIgnore]
public Dictionary Title { get; set; }
public int position { get; set; }
public bool template_is_carousel { get; set; }
public bool isVisible { get; set; }
public IList<string> filter { get; }
[Ignored]
public DisplayType display_type { get; set; }
[JsonIgnore]
public string DisplayType { get; set; }
public int parent_id { get; set; }
public string parent_type { get; set; }
public string image_url { get; set; }
public string banner_color { get; set; }
public int template_rows { get; set; } = 3;
public int template_columns { get; set; } = 2;
public Sector(Sector sector)
{
this.id = sector.id;
this.key = sector.key;
this.Title = sector.Title;
this.title = sector.title;
this.position = sector.position;
this.template_is_carousel = sector.template_is_carousel;
this.isVisible = sector.isVisible;
this.filter = sector.filter;
this.display_type = sector.display_type;
this.DisplayType = sector.DisplayType;
this.parent_id = sector.parent_id;
this.parent_type = sector.parent_type;
this.image_url = sector.image_url;
this.banner_color = sector.banner_color;
this.template_rows = sector.template_rows;
this.template_columns = sector.template_columns;
}
public Sector()
{
}
}
And this is how I m serializing my object :
private string serializeParameter(object parameter)
{
return JsonConvert.SerializeObject(parameter);
}

Serialization in Json.NET will serialize base class properties by default. The Sector class inherit from RealmObject class, then when serializing Sector object, all the base properties in the parent class RealmObject will be serialized.
To resolve this, you could try to use [JsonObject(MemberSerialization.OptIn)] attribute, in that case, properties without specify [JsonProperty] will not be serialized. For example, the following code will only serialize parent_type property,
[JsonObject(MemberSerialization.OptIn)]
public class Sector : RealmObject
{
[JsonProperty]
public string parent_type { get; set; }
}
Actually the simply way is to add [JsonIgnore] attribute for the properties in the parent class. But it looks like you are using a third package that you could not change the parent class RealmObject.
More details please reference
this thread.
To use which way is based on your requirements, you could also try to serialize it by Json relative APIs in UWP app without using the Json.Net. For example:
var jsonstring= Stringify();
public string Stringify()
{
JsonObject jsonObject = new JsonObject();
jsonObject["parent_type "] = JsonValue.CreateStringValue("test");
return jsonObject.Stringify();
}

Related

Json class saving a value while containing other default values

Hey all I am trying to figure out how to go about saving just one value in my JSON class instead of having to write the whole JSON out again with "New". I am using the Newton JSON.Net.
This is my JSON structure:
public class GV
{
public class Data
{
[JsonProperty("pathForNESPosters")]
public static string PathForNESPosters { get; set; }
[JsonProperty("pathForSNESPosters")]
public static string PathForSNESPosters { get; set; }
[JsonProperty("pathForSEGAPosters")]
public static string PathForSEGAPosters { get; set; }
[JsonProperty("pathToNESContent")]
public static string PathToNESContent { get; set; }
[JsonProperty("pathToSNESContent")]
public static string PathToSNESContent { get; set; }
[JsonProperty("pathToSEGAContent")]
public static string PathToSEGAContent { get; set; }
[JsonProperty("lastSavedVolume")]
public static double LastSavedVolume { get; set; }
}
public class Root
{
public Data data { get; set; }
}
And I have no issues with loading that data from a file into my class:
GV.Root myDeserializedClass = JsonConvert.DeserializeObject<GV.Root>(File.ReadAllText(
currentAssemblyPath + String.Format(#"\Resources\{0}", "dataForLinks.json")
));
But I have yet to find anything searching that will let me do one update to an object in the class without wiping it out doing a New statement.
What I am wanting to do is something like the following:
-Load the json into my class object [Done]
-Save a value thats in my class object [stuck here]
GV.pathToNESContent = "new value here";
-Save class object (with the one new value) back to the file for which it came from preserving the other original values. [not here yet]
When I update just that one class object I am wanting to contain the original values for all the other JSON data I read in from the file.
Anyone have a good example of the above you can share?
update
I'd ditch the inner class structure:
namespace GV
{
public class Data
{
[JsonProperty("pathForNESPosters")]
public string PathForNESPosters { get; set; }
[JsonProperty("pathForSNESPosters")]
public string PathForSNESPosters { get; set; }
[JsonProperty("pathForSEGAPosters")]
public string PathForSEGAPosters { get; set; }
[JsonProperty("pathToNESContent")]
public string PathToNESContent { get; set; }
[JsonProperty("pathToSNESContent")]
public string PathToSNESContent { get; set; }
[JsonProperty("pathToSEGAContent")]
public string PathToSEGAContent { get; set; }
[JsonProperty("lastSavedVolume")]
public double LastSavedVolume { get; set; }
}
public class Root
{
public Data Data { get; set; }
}
Deser (use Path.Combine to build paths, not string concat):
var x = JsonConvert.DeserializeObject<GV.Root>(File.ReadAllText(
Path.Combine(currentAssemblyPath, "Resources", "dataForLinks.json"))
));
Edit:
x.Data.PathToNESContent = "...";
and re-ser

Consume Data From this endpoint

I am getting tdata from a certain endpoint and the problem id on serialization to my classes. I want to cast the bellow data to my class but cant get how the class should be structured. Check out the data .....
{
"-LYG_AI_oGYjNBrzMlKF": {
"chatDispayText": "",
"chatId": "-LYG_AI_oGYjNBrzMlKF",
"chatName": "",
"chattype": "single",
"imageUrl": "https://wallpaper.wiki/wp-content/uploads/2017/04/wallpaper.wiki-Amazing-celebrities-hd-wallpaper-PIC-WPD004734.jpg",
"lastMessageSent": "aiye",
"lastMessageSentTime": 1549704416263,
"synched": false,
"users": {
"-LYG_AIZ5MvTbjR7DACe": "Uicpm3L15TX0c15pKCI6KUEARyB3",
"-LYG_AI_oGYjNBrzMlKE": "Xsr0z9lsqNOEytX61lJvaGz1A8F2"
}
}
}
If the data you get out the endpoint has a dynamic structure, you can make use of a key-vale pair collection or a dictionary. For instance:
JObject jObject = JObject.Parse(Data); // This would already give you a key-value pair collection
Dictionary<String,Object> collection = new Dictionary<String, Object>();
foreach(var obj in jObject){
collection.Add(obj.Key, obj.Value);
}
However, this isn't a strongly typed approach which means that it is not effective in the majority of scenarios. A better solution when dealing with endpoints would be to define a class with fixed schema, actually something you need in your code, and then map the class to the object yielded by the endpoint using a metadata struct. For example:
public class ChatInfoModel
{
[JsonProperty(Metadata.ChatId)]
public long ChatId { get; set; }
[JsonProperty(Metadata.ChatId, Required = Required.AllowNull)]
public String Message { get; set; }
}
public struct Metadata
{
public const String ChatId = "userChatId";
public const String Message = "messageTxt";
}
And then
var deserializedObject = JsonConvert.DeserializeObject<ChatInfoModel>(data);
However, if your class has the exact same naming convention (but should not necessarily follow the camelCase naming convention) for its properties as in the serialized data, the JsonProperty attribute would not be needed.
You can also deserialize the object without using JsonProperty attribute manually using the first approach, and it is actually advantageous in certain scenarios where your schema comes from a configuration file rather than a struct.
Take inspiration from the Structure below:
public class Rootobject
{
public LYG_AI_Ogyjnbrzmlkf LYG_AI_oGYjNBrzMlKF { get; set; }
}
public class LYG_AI_Ogyjnbrzmlkf
{
public string chatDispayText { get; set; }
public string chatId { get; set; }
public string chatName { get; set; }
public string chattype { get; set; }
public string imageUrl { get; set; }
public string lastMessageSent { get; set; }
public long lastMessageSentTime { get; set; }
public bool synched { get; set; }
public Users users { get; set; }
}
public class Users
{
public string LYG_AIZ5MvTbjR7DACe { get; set; }
public string LYG_AI_oGYjNBrzMlKE { get; set; }
}

Deserialize Json for CRM Entities

I have the following Json defining a specific configuration which has to be stored in custom CRM entities:
{
"useraccountid": "U12345",
"profiles": [
{
"applicationrole": "RelationshipManager",
"maindatascopetypecd": 858000001,
"organisationalunitno": "10000000",
"ishierachical": 1
},
{
"applicationrole": "CountrySpecialist",
"maindatascopetypecd": 858000002,
"attributetypecd": 858000000,
"attributevalue": "SY",
"isreadonly": 0
}
]
}
Each user can have multiple user provisioning profiles. this data finally needs to be written into custom CRM entities. The "useraccountid" is a lookup to a systemuser (entityreference).
What I already have is e deserializer like this:
public static T JsonDeserialize<T>(string jsonString)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
T obj = (T)ser.ReadObject(ms);
return obj;
}
And classes like this for the parent class:
[DataContract]
class CrmUserProvisioning
{
[DataMember]
public String clm_useraccountid
{
get; set;
}
// will be set on runtime
public DateTime clm_createdon
{
get; set;
}
[DataMember]
public List<CrmProfile> clm_profiles { get; set; } = new List<CrmProfile>();
}
and for the profile(s)
[DataContract]
public class CrmProfile
{
[DataMember]
public Guid clm_userprovisioningid
{
get; set;
}
[DataMember]
public string clm_applicationrole
{
get; set;
}
[DataMember]
public int clm_maindatascopetypecd
{
get; set;
}
[DataMember]
public string clm_organisationalunitno
{
get; set;
}
[DataMember]
public bool clm_ishierachical
{
get; set;
}
[DataMember]
public int clm_applyingtypecd
{
get; set;
}
[DataMember]
public int clm_globalopenaccesscd
{
get; set;
}
[DataMember]
public int clm_attributetypecd
{
get; set;
}
[DataMember]
public string clm_attributevalue
{
get; set;
}
[DataMember]
public bool clm_isreadonly
{
get; set;
}
}
missing fields in the config for the profile will not be deserialized. I'm stuck with the fact on how deserialize this config regarding the fact that the config can contain many profile classes but only one parent class (UserProvisioning).
Could anybody put me in the right direction? Any help is really appreciated.
kind regards
UPDATE 02.03.2018
After having deserialized the Jsion into object(s) I need to store now the objects into the corresponding Microsoft Dynamics CRM entites. The entities and the attributes are named like the object- and the property-names.
I already have the organisation service, etc. I only need to know how to map the objects to a regular crm create or update request.
If somebody could help me out with this, it would be very appreciated.
Use DataContract and DataMember
[DataContract]
class UserProvisioning
{
[DataMember]
public String useraccountid
{
get { return this.useraccountid; }
set { this.useraccountid = value; }
}
// Will be set on runtime
public DateTime createdon
{
get { return this.createdon; }
set { this.createdon = value; }
}
// Must declare this for the child list of Profile
[DataMember]
public List<Profile> profiles {get;set;}=new List<Profile>();
}
In CrmProfile also set DataContract for the class and DataMember for the properties.
Check the docs:
DataContract
DataMember. Only the properties with DataMember will serialize.
You can also set required properties or set not to serialize default values.

Xml Serialization for list Property doesn't work when one item in the list

<TotalRecords ItineraryCount='1' >
<Recs ItineraryNumber="1" >
<Amount>516.6</Amount>
<TravelTime>940</TravelTime>
<FSegment>
<OutProperty>
<Segment No="1">
<Name>Ronald</Name>
<City>London</City>
<Country>United Kingdom</Country>
</Segment>
<Segment No="2">
<Name>Richard</Name>
<City>
London
</City>
<Country>United Kingdom</Country>
</Segment>
</OutProperty>
</FSegment>
</Recs>
</TotalRecords >
I am serializing xml to object of TotalRecords Class. It works fine when there are more than one segment in the OutProperty but in case of one segment it doesn't serialize into list property.
I have also tried with [XmlArray("")] and [XMlArrayItem("")] but it doesn't work. Anyone have idea?
public class TotalRecords
{
public Recs recs { get; set; }
public string ItineraryCount { get; set; }
}
public partial class Recs
{
public string amountField { get; set; }
public string travelTimeField { get; set; }
public FSegment fSegmentField { get; set; }
public string itineraryNumberField { get; set; }
}
public class FSegment
{
public List<Segment> OutProperty {get;set;}
}
public class Segment
{
public string nameField { get; set; }
public string cityField { get; set; }
public string countryField { get; set; }
}
Try to use the following for your Classes and their Properties:
[DataContract]
public class Contact
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
Hacking like this helps in many cases, perhaps in your too (converting List to array):
public class FSegment
{
[XmlIgnore]
public List<Segment> OutProperty {get;set;}
[XmlArray("OutProperty");
public Segment[] _OutProperty
{
get { return OutProperty.ToArray(); }
set { OutProperty = new List<Segment>(value); }
}
}
I am not exactly sure how your provided class definition worked previously without any XML attribute/element definitions since your variable names are not the same as the XML identifiers, meaning that the serialization wouldn't populate the properties that it couldn't find a name for.
Nether the less, the main issue here is that you are trying to put a list into a normal property.
From the XML provided, OutProperty is a single sub element of FSegment and Segment is an array of sub elements of OutProperty, but in your provided code, you tried to make Segment an array sub element of FSegment.
The correct structure of the class definition should be as follows (also including the XML definitions)
[System.Xml.Serialization.XmlRoot(ElementName="TotalRecords")]
public class TotalRecords
{
[System.Xml.Serialization.XmlElement(ElementName="Recs")]
public Recs recs { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryCount")]
public string ItineraryCount { get; set; }
}
public partial class Recs
{
[System.Xml.Serialization.XmlElement(ElementName = "Amount")]
public string amountField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "TravelTime")]
public string travelTimeField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "FSegment")]
public FSegment fSegmentField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryNumber")]
public string itineraryNumberField { get; set; }
}
public class FSegment
{
[System.Xml.Serialization.XmlElement(ElementName = "OutProperty")]
public SegmentList OutProperty { get; set; }
}
public class SegmentList
{
[System.Xml.Serialization.XmlElement(ElementName = "Segment")]
public List<Segment> segmentField { get; set; }
}
public class Segment
{
[System.Xml.Serialization.XmlElement(ElementName = "Name")]
public string nameField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "City")]
public string cityField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "Country")]
public string countryField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "No")]
public int segmentNoField { get; set; }
}
Please note that in the above structure, Segment is a list object under the OutProperty object, which resides under the FSegment object.
Using this class structure to load your XML produces the (assumed) correct data in the created objects.
Using the XML definitions allows you to decouple the actual names of class properties from what they are called in the XML data. This allows you to changes the one or the other without affecting the other one, which is useful when you don't control the creation of the XML data.
If you don't want all the XML definitions in your code, change the names of the classes so that you can name your properties the same as what they are called in the XML file. That will allow you couple everything directly

How to go about combining two objects, manipulate the data, then separate them?

I have two classes with some similar fields, some different, and a form that utilizes two different objects depending on what mode it's in (insert/edit).
Instead of using two different objects and if statements checking the form mode, I'd like to have one struct to be hydrated with either of the two objects fields so I can manipulate one object through the page life-cycle. Then separated the struct back to its respective object for insert/updating the DB.
Example of classes:
public partial class SomeClass
{
public Int32 B {get;set;}
public String C {get;set;}
public Boolean D {get;set;}
}
public class SomeOtherClass
{
public Int32 A {get;set;}
public Int32 B {get;set;}
public String C {get;set;}
}
Update with Solution Example:
public interface IInsertable
{
string SharedName { get; set; }
string SharedID { get; set; }
string editedFieldValue { get; set; }
long GetSuperSecreteInfo();
}
internal class InsertableImplementation : IInsertable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return -1;
}
}
public interface IUpdateable
{
string SharedName { get; set; }
string SharedID { get; set; }
string updatedFieldValue { get; set; }
Guid GenerateStevesMagicGuid();
}
internal class UpdateableImplementation : IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
public static class WonderTwinFactory
{
public static WonderTwins GenerateWonderTwin(IUpdateable updateable, IInsertable insertable)
{
var wt = new WonderTwins();
// who will win?
wt.SharedID = updateable.SharedID;
wt.SharedID = insertable.SharedID;
// you decide?
wt.SharedName = updateable.SharedName;
wt.editedFieldValue = "stuff";
return wt;
}
}
public class WonderTwins : IInsertable, IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return 1;
}
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
class Program
{
static void Main(string[] args)
{
IUpdateable updateable = new UpdateableImplementation();
IInsertable insertable = new InsertableImplementation();
WonderTwins dualImplementatin = WonderTwinFactory.GenerateWonderTwin(updateable, insertable);
IUpdateable newUpdateable = dualImplementatin as IUpdateable;
IInsertable newInsertable = dualImplementatin as IInsertable;
}
}
Have both classes implement an interface that defines the operations common to each, including both the fields that are shared (assuming the view needs to access them) and also a method to actually perform the operation that they represent (insert/edit).
Other way of doing such things is using C# dynamic object and assign properties directly. It may help to avoid any new type or interface and directly utilizing new dynamic object any time, as much as required.
var newObject = new {
objectOfClass1 = x.prop1,
objectOfClass2 = x.prop2
}

Categories