I am trying to get an object to deserialize into itself. I have tride the following:-
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
}
public void load(string fname)
{
string s = File.ReadAllText(fname);
this = JsonConvert.DeserializeObject<JobID>(s);
}
But the word this is 'read only' according to the error I get.
I have used 'this.jobname = "X";' before so clearly 'this' is not read only.
I am using Newtonsof.Json.
Why not use static method to load the object. Such as :
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
public static JobId Load(string fname){
string s = File.ReadAllText(fname);
return JsonConvert.DeserializeObject<JobID>(s);
}
}
Although you can assign a value to a property of 'this', you can't change the object to which 'this' refers to.
The 'this' keyword refers to the current object instance in the context (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/this).
Assuming the Load function is inside another object (or static), you could do something like:
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
}
public class JobReader
{
// Property to store deserialized object
public JobID Job { get; set; }
public void load(string fname)
{
string s = File.ReadAllText(fname);
// Assign object to property.
this.JobID = JsonConvert.DeserializeObject<JobID>(s);
}
}
You can use the static method as suggested by Xbotter to create a new instance. But for some reason if you want to deserialize the file content into current object only, then easiest way would be:
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
public void load(string fname)
{
string s = File.ReadAllText(fname);
JobID tmp = JsonConvert.DeserializeObject<JobID>(s);
copy(tmp);
}
public void copy(JobID tmp)
{
this.jobname = tmp.jobname;
// do the same for other properties that you want to copy
}
}
If you want to do this without a static method, you can use the JsonSerializer.Populate method. Example code:
public class JobID
{
public string jobname;
public string first;
public string second;
public string third;
public string clientName;
public string workflow;
public void load(string fname)
{
string s = File.ReadAllText(fname);
new JsonSerializer().Populate(new JsonTextReader(new StringReader(s)), this);
}
}
Anssssss provided the answer I've been looking for years. Thank you!
This is how I used it:
bool bOk = false;
StreamReader myFileStream = null;
Newtonsoft.Json.JsonSerializer mySerializer = new Newtonsoft.Json.JsonSerializer();
try
{
myFileStream = File.OpenText(sFilePath);
mySerializer.Populate(myFileStream, this);
bOk = true;
}
catch (Exception e)
{
string sException = e.ToString();
CHelper.ThrowException(new Exception(sException + "\n\n" + sFilePath));
}
finally
{
if (myFileStream != null)
{
myFileStream.Close();
}
}
return bOk;
Related
I have a 'complex' object that I want to serialize with JSon.Convert. As 'complex' objects go it is rather simple: Here are the objects:
The main object:
public class CustomerContactRequest
{
private RequestHeaderArea header;
private RequestPayloadArea payload;
public CustomerContactRequest(string headerMessage, string npsGroup, string npsSection)
{
this.header = new RequestHeaderArea(headerMessage);
this.payload = new RequestPayloadArea(npsGroup, npsSection);
}
}
The 'header' Object:
public class RequestHeaderArea
{
private string headerMessage;
public string HeaderMessage { get { return headerMessage; } }
public RequestHeaderArea(string headerMessage)
{
this.headerMessage = headerMessage;
}
}
The Payload Area:
public class RequestPayloadArea
{
private string npsGroup;
private string npsSection;
public string NPSGroup { get { return npsGroup; } }
public string NPSSection { get { return npsSection; } }
public RequestPayloadArea(string npsGroup, string npsSection)
{
this.npsGroup = npsGroup;
this.npsSection = npsSection;
}
}
And Finally, the main process:
static void Main(string[] args)
{
CustomerContactRequest ccRequest = new CustomerContactRequest(
headerMessage: "test",
npsGroup: "1234567",
npsSection: "0000");
retrieveContactInfo(ccRequest);
}
static void retrieveContactInfo(CustomerContactRequest ccRequest)
{
string jsonRequest = JsonConvert.SerializeObject(ccRequest);
// code to call service
}
jsonRequest returns {} even though ccRequest contains the expected values. What am I missing?
I am expecting something like this (sans formatting):
{
"headerArea": {
"messageId": "test"
},
"payloadArea": {
"group": {
"Number": "1234567",
"Suffix": "0000"
}
}
}
Implementing Chris's answer my classes now look like below (main program did not change except that I added Formatted.Indented to the SerializeObject call to make it pretty):
CustomerContactRequest:
public class CustomerContactRequest
{
public RequestHeaderArea headerArea;
public RequestPayloadArea payloadArea;
public CustomerContactRequest(string headerMessage, string npsGroup, string npsSection)
{
this.headerArea = new RequestHeaderArea(headerMessage);
this.payloadArea = new RequestPayloadArea(npsGroup, npsSection);
}
}
RequestHeaderArea:
public class RequestHeaderArea
{
private string messageId;
public string MessageId { get { return messageId; } }
public RequestHeaderArea(string headerMessage)
{
this.messageId = headerMessage;
}
}
RequestPayloadArea:
public class RequestPayloadArea
{
public Group group;
public RequestPayloadArea(string npsGroup, string npsSection)
{
this.group = new Group(npsGroup, npsSection);
}
}
And a new class: Group:
public class Group
{
public string Number;
public string Suffix;
public Group(string npsGroup, string npsSection)
{
Number = npsGroup;
Suffix = npsSection;
}
}
Now my Json looks exactly as expected (see green text above)
SerializeObject ignores private members by default. You can either make them public, or by adding the SerializableAttribute to your CustomerContractRequest class.
I'm trying to access member values of the following class:
public class EditorialDateFormat
{
public string en; <------ TRYING TO GET ITS VALUE
public string fr; <------ OR THIS VALUE
public string Default;<-- OR THIS ONE
}
public class Params
{
public string Template;
public string MainTagID;
public string[] NavigationFilters;
public EditorialDateFormat EditorialDateFormat;
}
public class Site
{
public string Name;
public string CreationFolder;
public Params Params;
public string[] Feed;
public string Endpoint;
public string[] TargetDatabases;
}
I could do it easily like :
site.Params.EditorialDateFormat.en(for example) but "en" string is actually saved in a variable.
I tried the following code :
// Myvariable contains "en"
object c = GetPropValue(site.Params.EditorialDateFormat, MyVariable);
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetMember(propName);
}
But it returns me a MemberInfo object without the member value
I would appreciate some help!
Thanks in advance
You want to read field (public instance field's value), that's why we put GetField:
//TODO: rename the method: it doesn't read property (Prop)
public static object GetPropValue(object src, string propName) {
return src
.GetType()
.GetField(propName, BindingFlags.Public | BindingFlags.Instance)
.GetValue(src);
}
public class EditorialDateFormat
{
private string _en;
public string en
{
get { return !string.IsNullOrEmpty(_en) ? _en : fr; }
set { _en = value; }
}
private string _fr;
public string fr
{
get { return !string.IsNullOrEmpty(_fr) ? fr : Default; }
set { _en = value; }
}
public string Default { get; set; }
}
and you can use it like var c=site.Params.EditorialDateFormat.en
in elegant way
I am trying to use JavaScriptSerializer and I have got good results when I want to serialize a list of objects of a class like
public class employee
{
public string id; //unique id of the employee
public string displayName;
public int displayFlag;
public employee(string i, string dN, int dF)
{
id = i;
displayName = dN;
displayFlag = dF;
}
}
public class data2
{
public List<employee> detail;
}
When I do the following
var json = new JavaScriptSerializer();
string jsonData = json.Serialize(data2);
(and data2 is an object of class data2)
However when I try to do the same for something a little more complicated such as
public class Ccanister
{
string identifier;
public Ccanister(string c)
{
identifier = c;
}
}
public class medicine
{
public string id; //unique id
public string displayName;
//and here an array of canisters
public List<Ccanister> canister;
}
public class dataMedicine
{
public List<medicine> detail; //Change this
}
and I do this
string jsonMedi = json.Serialize(dataM);
I got wrong results.
dataM has correct results (I debugged it) but when jsonMedi gets its results, the canister list 'canister' is always empty. (It was not empty in dataM)
I wonder what I am doing wrong here
I have the following class:
[Serializable]
public class ClassOne : ClassTwo
{
private string _parameterOne;
private string _parameterTwo;
private string _parameterThree;
public Category (string parameterOne, string parameterTwo, string parameterThree)
{
_parameterOne = parameterOne;
_parameterTwo = parameterTwo;
_parameterThree = parameterThree;
}
}
I then want to make use of the XMLSerializer:
private void Serialize()
{
XmlSerializer xmlSerializer = new xmlSerializer(typeof(ClassOne));
xmlSerializer.Serialize(stream, object);
}
However, I can't serialize that class because it does not have a parameterless construction... How can I practically resolve this situation?
Add empty constructor. And you should use public properties for fields that you want to serialize
[Serializable]
public class ClassOne : ClassTwo
{
private string _parameterOne;
private string _parameterTwo;
private string _parameterThree;
public Category() { }
public Category (string parameterOne, string parameterTwo, string parameterThree)
{
_parameterOne = parameterOne;
_parameterTwo = parameterTwo;
_parameterThree = parameterThree;
}
}
I am serializing with xml, and I had it working with just a simple class, but when I made a secondary class, of which the simple class was just a component, the serialization stopped working. It fails with an "Error reflecting type" error at the serialization stage. The code is as follows:
public class CustomField
{
[XmlAttribute("FieldID")]
public string FieldID;
[XmlAttribute("FieldValue")]
public string FieldValue;
public CustomField() { }
public CustomField(string fieldID, string fieldValue)
{
this.FieldID = fieldID;
this.FieldValue = fieldValue;
}
}
[XmlType("Entry")]
public class CustomEntry
{
[XmlAttribute("Author")]
public string Author;
[XmlAttribute("Title")]
public string Title;
[XmlAttribute("Trial")]
public string Trial;
[XmlAttribute("Responses")]
public List<CustomField> Responses;
public CustomEntry() { }
}
public static class EntrySerializer
{
public static void SerializeObject(this CustomEntry entry, string file)
{
var serializer = new XmlSerializer(typeof(CustomEntry));
using (var stream = File.OpenWrite(file))
{
serializer.Serialize(stream, entry);
}
}
}
Is it a labeling issue with the Xml markers, or is it something else?
Try defining your serializer like this:
var serializer = new XmlSerializer(typeof(CustomEntry), new Type[] { typeof(CustomField) });
You need to inform the serializer of the additional types it is expecting to serialize.
I usually tag with XMLRoot (two places). I need to see sample of XML to give better answer.
[XmlRoot("CustomField")]
public class CustomField
{
[XmlAttribute("FieldID")]
public string FieldID;
[XmlAttribute("FieldValue")]
public string FieldValue;
public CustomField() { }
public CustomField(string fieldID, string fieldValue)
{
this.FieldID = fieldID;
this.FieldValue = fieldValue;
}
}
[XmlRoot("Entry")]
public class CustomEntry
{
[XmlAttribute("Author")]
public string Author;
[XmlAttribute("Title")]
public string Title;
[XmlAttribute("Trial")]
public string Trial;
[XmlAttribute("Responses")]
public List<CustomField> Responses;
public CustomEntry() { }
}