I have a collection of simple elements in C#. Element is like:
public class Element
{
public string AName { get; private set; }
public string PName { get; private set; }
public string Value { get; set; }
}
I need to pass this collection as a string to a Python script. And in python for each element I need to call function like Func(AName, PName, Value). I've done this by serializing collection to JSON in C# and in python write code:
elements = json.loads(JSON)
for element in elements:
Func(routeLayer, element['AName'], element['PName'], element['Value'])
But now it turns out that I cannot use Python's json module. So I need a new way to pass this collection to script and dont use any additional modules. I am a real noob in Python, so solutions I can imagine are ugly. Can you give me an advice?
If there is some character which you can guarantee is not in the strings for AName,PName and Value then you could use that character as a separator.
In C#, you could "serialize" the information by simply joining the three strings with the separator, e.g. "foo,bar,baz".
Then in Python, the information could be deserialized with
aName,pName,value = element.split(',')
PS. Just out of curiosity, why can't you import modules in the standard library?
The most common standard, which should be available in Python as well is XML. Did you consider this option?
UPDATE:
You can use XmlSerializer in C# to serialize as XML. And here is something, what i've found for Python
Related
I am trying to deserialize an attribute with a list of pages to a List<String> object. If I use a space delimiter, I am able to deserialize it just fine, but I want it to look cleaner with a comma or a vertical bar.
Is it possible to deserialize
<Node Pages="1,2">
into a List<String> or List<int>?
My class is simple as well.
public List<int> Pages;
XmlSerializer does not support this out of the box for attributes. If you are in control of the structure of the XML, consider using child elements because using character separated attribute strings kind of beats the purpose of XML altogether.
You could work around it though using a computed property. But bear in mind that this will be slower because every time you access this property, you will parse the comma-separated string.
[XmlAttribute(AttributeName = "Pages")]
public string PagesString { get; set; }
public IList<int> Pages {
get {
return PagesString.Split(',').Select(x => Convert.ToInt32(x.Trim())).ToList();
}
set {
PagesString = String.Join(",", value);
}
}
Also, this silly implementation does not take into account that there might be wrong input in your string. You should guard against that too.
Another thing to notice is that every time you access the Pages property, a new collection is returned. If you invoke Add() on the returned value, this change will not be reflected in your XML.
I have a relatively simple C#class that I would like to marshal into a VB project. It looks like this (I simplified a bit for this post):
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-123456789ABC", ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
[ProgId("MyBiz.MyResponse")
[Serializable]
public class MyResponse
{
public bool Success { get; set; }
public int ID{ get; set; }
public string Location{ get; set; }
public ArrayList Messages { get; set; }
}
Messages contains 0 or more strings. I compile this and create a type library to be used by VB6. Everything work well in terms of data getting passed from the simple types, but the Messages variable, while the VB runtime recognizes it as an ArrayList, does not contain any data in it even when it should. What am I missing, in terms of marshaling the data? I know that generics do not marshal, but I believe an ArrayList does. Am I missing an attribute, or something else?
No need to offer alternative solutions, as I am asking this because I want to know how to do it, not because I don't have alternatives if I can get this to work. Thanks!
One way to handle this is to use a COM SafeArray to pass data back and forth from .NET to COM. I have had better luck with this technique than with a ArrayList. The declaration for your Messages could look like:
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public string[] Messages
This would be seen in VB6 or similar COM client as
Public Messages() as String
a COM SafeArray of Strings.
There is an API which I don't control, but whose output I need to consume with C#, preferably using JSON.Net.
Here's an example response:
[
{
"media_id": 36867,
"explicit": 0
}
]
I had planned to have a class like so:
class Media {
public int media_id;
public int explicit;
}
And to deserialize:
var l = JsonConvert.DeserializeObject<List<Media>>(s);
Unfortunately, "explicit" is a C# keyword, so this can't compile.
My next guess is to modify the class:
class Media {
public int media_id;
public int explicit_;
}
... and somehow map the response attributes to the C# attributes.
How should I do that, or am I totally going at this the wrong way?
Failing that, I'd be OK to just plain ignore the "explicit" in the response, if there's a way to do that?
Haven't used JSON.Net, but judging by the docs here, I figure you just need to do what you'd do with XmlSerialization: Add an attribute to tell how the JSON property should be called:
class Media {
[JsonProperty("media_id")]
public int MediaId;
[JsonProperty("explicit")]
public int Explicit;
}
C# lets you define members with reserved word names (for interoperability cases exactly like this) by escaping them with an #, e.g.,
class Media {
public int media_id;
public int #explicit;
}
Not sure how this plays with JSON.Net, but I would imagine it should work (since the # is an escape and not actually part of the field name).
The following code worked for me.
class JsonRpc {
public string id;
public string method;
public string[] #params;
}
JsonConvert.DeserializeObject<JsonRpc> (data)
Thanks everyone
I want to serialize a class. In this class there's a property of type Class1 that in turn has its own properties.
public abstract class ComponentBase
{
[ToSerialize] //An attribute defined my me, indicating whether or not to serialize this property.
public ComponentArgs Parameters { get; set; }
}
public class ComponentArgs
{
public string WorkingPath { get; set; }
public IList<Language> Languages { get; set; }
public string ComponentOutputPath { get; set; }
}
The information serialized must be put into a Dictionary<string,string>, such as
ComponentSettings[str_Name] = str_Value;
The method used in reading this value is Reflection
// pinfo: Property Info got via Type.GetProperties();
componentSettings.Add(pinfo.Name, pinfo.GetValue((object)this, null).ToString());
The information after serialization is:
<Parameters>MS.STBIntl.Pippin.Framework.ComponentArgs</Parameters>
instead of the value of ComponentArgs.WorkingPath.
The solution I thought of is to append to the following line an if judgement:
componentSettings.Add(pinfo.Name, pinfo.GetValue((object)this, null).ToString());
if(pinfo is ComponentArgs)
componentSettings.Add(pinfo.Name, pinfo.GetValue(
(ComponentArgs)this, null).WorkingPath+"\n"+
LanguageList+"\n"+ //Language list is a concatinated string of all elements in the list.
(ComponentArgs)this, null).ComponentOutputPath+"\n"+
);
When deserializing, add a judgement of whether the value contains more than 2 "\n", if so, extract each value from the string.
But this way seems clumsy and much more like an workaround. I wonder if there's any more professional way of doing it? My reviewer is very particular and he won't accept such a solution. If you know a way, could you please share it with me? Thanks a lot.
There are lots of ways to use inbuilt serialization.
The simplest and oldest is the [Serializable] attribute that tells .NET to serialize the members.
You can also use the WCF [DataContract] attribute to serialize stuff.
There is also the IXMLSerializable interface which allows you to implement custom XML readers and writers for you classes.
The bottom line is, there is no need to roll your own - it has been done.
I need to deserialize some JavaScript object represented in JSON to an appropriate C# class. Given the nice features of automatic properties, I would prefer having them in these classes as opposed to just having fields. Unfortunately, the .NET serialization engine (at least, by default) totally ignores automatic properties on deserialization and only cares about the backing field, which is obviously not present in the JavaScript object.
Given that there's no standard way to name backing fields and to be honest I don't even want to bother with the "let's create a JavaScript object that looks like it had C# backing fields" approach as it sounds a bit dirty, the only way I could serialize JavaScript fields to C# auto-properties if I could force the serialization engine to somehow ignore the backing field and use the property directly. Unfortunately, I can't figure out how this is done or if this can be done at all. Any ideas would be appreciated.
EDIT: Here's an example:
Javascript:
function Cat()
{
this.Name = "Whiskers";
this.Breed = "Tabby";
}
var cat = new Cat();
This is then serialized to "{Name: 'Whiskers'}".
The C# class:
[Serializable()]
public class Cat
{
public string Name { get; set; }
public string Breed { get; set; }
}
And the deserialization code, that fails:
new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream);
And it is apparent from the exception that it fails because it is looking for the backing field.
EDIT2: Here's the exception, if that helps (no inner exceptions):
System.Runtime.Serialization.SerializationException
"The data contract type 'Test.Cat'
cannot be deserialized because the
required data members
'<Name>k__BackingField, <Breed>k__BackingField' were not
found."
What's happening here is the deserializer is trying to guess the name of your backing fields.
You can solve this by adding explicit mappings (DataContract/DataMember attributes) like this:
[DataContract]
public class Cat
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Breed { get; set; }
}
You can do this with JavaScriptSerializer found in the System.Web.Script.Serialization namespace:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Cat c = serializer.Deserialize<Cat>(jsonString);
I have POCO objects with automatic properties and this works just fine.
EDIT: I wrote about JSON Serializers in .NET which compares this serializer with DataContractJsonSerializer.
baretta's answer solved the k__BackingField bloat for me. Just a tiny addendum that you can decorate this class to auto serialize into either XML or JSON in a similar way:
[Serializable, XmlRoot, DataContract]
public class Cat
{
[XmlElement]
[DataMember]
public string Name { get; set; }
[XmlElement]
[DataMember]
public string Breed { get; set; }
}
... and then use a DataContractJsonSerializer or XmlSerializer to prepare it for your endpoint.
I'm assuming you are passing data via a web service. If you are using the WebService class with the ScriptMethod attribute uncommented-out, the web service methods can read JSON natively. They even use the same JavaScriptSerializer that was mentioned above. If you are using WCF I'm a little more fuzzy on the logic.
But make sure your JSON object are returning data for EVERY property in your class. In your error, there is mention of a Breed property that is not in your example.
Also, on the JavaScript side, do to the dynamic nature of JavaScript it is easy to add new properties to your objects. This can sometimes lead to circular references. You should remove any extra data that you might have added (just as you are sending data via the web method, then add it again once you are done).