I'm using IronPython as a scripting language in my C# application. One of the "features" that I've implemented is the ability for a script to persist values, which are then exposed to the next script being executed. This is achieved by passing the value(s) to be stored to a C# class, exposed to the script by the "host" application. The code to store a value looks something like this:
store.set("xyz", 123)
('store' is the variable through which the C# object is exposed).
Internally the C# class stores these name/value pairs in a Dictionary<string, object>. When the script finishes executing it serialises the dictionary using Json.Net (var json = JsonConvert.SerializeObject(dict)) and writes the resulting string to file.
When the next script is run, the "host" C# application reads and deserialises the file (JsonConvert.DeserializeObject<Dictionary<string, object>>(s)) and exposes the name/value pairs to the script via the same C# class, which the script can access like this:
my_var = store.get("xyz")
This feature has been working fine with simple types such as ints and floats, but one of our users now needs to persist a list of ints. It works to a fashion - the list gets persisted and exposed to the next Python script, but at this point it is now a JArray type (something to do with Json.Net it seems). This doesn't play nicely with the Python code (which is expecting a list of ints).
I guess the simplest fix is to convert this JArray to a Python int list. But how?
Alternatively it would be nice if the issue could be "fixed" in the C# class (casting?), to avoid users from having to do this conversion in their scripts. However I don't want to change the de/serialisation process to the extent that it no longer reads users' existing data files. Thoughts?
I've found a solution with only minimal impact on script authors. In my C# code, after deserialising the file, I go through the dictionary looking for items with a value of type JArray, and convert them to arrays:
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var keys = dict.Keys.ToList();
foreach (var key in keys)
{
var jarray = dict[key] as JArray;
if (jarray != null)
{
dict[key] = jarray.ToObject<object[]>();
}
}
These arrays are then exposed to the Python script as before; as they are C# arrays the script authoer must convert to Python lists, which is trivial:
my_var = list(store.get("xyz"))
Related
I’m trying to create an object of Dictionary<Cottle.Value, Cottle.Value> (Cottle is a templating engine that uses it’s own type for storing keys and values to replace {key} text with values in a template) from a json string that doesn’t have nested values so that each and any pair of json key/values gets converted to a dictionary keyvaluepair…but the best I’ve managed to do so far is create a Dictionary<string, string> thus leaving me with the problem of creating Cottle.Value from string which can actually be done by calling Value.FromString(string) but doing that requires going through a foreach loop, so I’m just wondering is there a more direct way to do that? TIA
P.S.
Unfortunately, I’m not using Newtonsoft to create a custom converter and may have missed the way to the same with System.Text.JSON so that could be an easiest solution if still possible but seems too complicated for a simple thing I’m trying to do…adding it to a webapi.
I have the majority of my code base in c# where data is entered into a datagrid in a GUI and then this is taken into a set of python3 functions to interrogate the data further.
From the datagrid information , user defined objects containing boolean, float and dictionary properties are populated which are then passed into python.
Currently the python code is using only python functionality and I think this may be the issue as the dict.keys() method in the python funciton is not recognising the C# dictionary that is passed in.
Is there an easy way to convvert the c# dictionary into a python dictionary so that the python code can be unchanged?
Thanks!
A quick and dirty work around would be to use NewtonSoft nugget to serialize your class contents (in this case, your dictionary) and convert it into a JSON.
using Newtonsoft.Json
var myDictionary = new Dictionary<string,string>();
myDictionary.Add("key1","value1");
myDictionary.Add("key2","value2");
//Now convert the dictionary into json.
var jsonToSend = JsonConvert.SerializeObject(myDictionary);
Now pass in that jsonToSend to the python code and at the python code, load the json into a dict using json module like below:
import json
passedin_json = 'the output of your method that receives the json'
loaded_json_data = json.loads(passedin_json)
And done, Now you've successfully transferred your C# dictionary to your python dict
Context: ClearScript, JScript, C#, Windows, Azure
In my ClearScript-enabled projects, I have a Dictionary<string,object> that I use for passing data into, around inside and back out of evaluated scripts.
On the C# side I have
static Dictionary<string, object> Settings = new Dictionary<string, object>();
and then later on
JSengine = new JScriptEngine(WindowsScriptEngineFlags.EnableDebugging | WindowsScriptEngineFlags.EnableJITDebugging);
and
JSengine.AddHostObject("CSSettings", Settings);
On the JScript side I have things like
CSSettings.Add("your API key", CSConfig.Retrieve("api.key"));
for setting values.
The challenge at the moment is updating a value in the Dictionary. The following works
CSSettings.Item("id") = Wfm_AccNumber;
it's just that it's non-standard JScript. What's more the JSHint tool that I'm using inside of Notepad++ complains.
I could do a .Remove() before the .Add(), I suppose but is there a better way?
The following should work:
CSSettings.Item.set("id", Wfm_AccNumber);
value = CSSettings.Item.get("id"); // or CSSettings.Item("id")
This may look a bit clunky, but it's standard JavaScript and should work with all .NET indexers (which aren't always named "Item", and can have more than one parameter).
I am trying to implement a PHP function I have already made in C# but I have no idea of the syntax used in C# used to Navigate Dictionaries! (Associative arrays in PHP). What I am doing essentially is making a foreach loop to print each instance of a property in the associative array. I'm not sure if my question is completely clear so to make it easier, What would be the C# equivalent of this?
foreach ( $data->response->docs as $info )
{
echo "{$info->EventId},";
echo "{$info->VenueName},";
}
I just need a nudge in the right direction syntax wise.
Thanks
EDIT-
oops, when I posted this question I was tired. my problem is how to navigate a dictionary serialized from JSON. in my example I was parsing two properties from this sample data :-
{"responseHeader":{"status":0,"QTime":2},"response":{"facet_counts":{},"numFound":110,"docs":[{"VenueSEOLink":"/Aberdeen-Music-Hall-tickets-Aberdeen/venue/443660","VenueId":"10512085.....
etc etc....
So I am trying to figure out how to go down multiple levels through the dict. (C# equivalent of ->)
In C#, you can use a System.Collections.Dictionary or a generic System.Collections.Generic.Dictionary<TKey, TObject>. I recommend the generic dictionary because it is strongly-typed and you don't have to cast the contents every time you retrieve an object.
Assuming your EventId is an int, you can access it like this:
Dictionary<int, string> info = new Dictionary<int, string>();
int eventId = 42;
info[eventId] = "Some value";
var value = info[eventId];
// value = "Some value" as string
If you are using string keys just change the dictionary definition and key type from int to string.
To iterate on a dictionary (or any collection or other object that implements IEnumerable), you use essentially the same syntax as in PHP:
foreach (var item in info) {
// Do something with item
}
More info Systems.Collections.Generic.IDictionary is here.
I've created a linked list class in my JavaScript code and then translated that code into C#.
Right now I have a JavaScript function that calls a Web Service in order to get an array of names, the JavaScript onComplete function then takes that array and makes it into a linked list.
Is there any way I can create the linked list in the Web Service and pass it back to be used by the JavaScript code or can linked lists not transfer properly?
Edit: Let me rephrase my question to something that makes a little more sense. If you have a custom made object created by a class say.... class User, and that class has a variable called user name. If you pass a User object: objUser, back from C# to JavaScript, how does the JavaScript know it can access objUser.userName? What about possible methods it can invoke on this user object?
I had a similar question when I was creating my ASP.NET MVC application. Basically the answer is that JavaScript does not have the same concept of Types as in C#.
Let's say that you've decided to use JSON to pass data between your client and server in your application. The choice of JSON, XML, YAML or other format is not important.
Server Side
On your server side, in your C# code, you can do something like this (assuming you are using a JSON library of some sort):
var myLinkedList = JsonConvert.DeserializeObject<LinkedList>(json);
Now you've got a myLinkedList variable of Type LinkedList. myLinkedList now behaves like all LinkedList instances.
Client Side
However on the client site, in your JavaScript code, you probably do something like this:
function LinkedList(){
//Constructor for your LinkedList
};
LinkedList.prototype = {
//Various functions to operate on your linked list
};
You need to write something like this to deserialize the data that returns from the server:
var linkedList = JSON.parse(jsonString);
Note that there is NO WAY to indicate that you want this deserialized data to go into the LinkedList "class" that you've defined earlier. JavaScript does not understand that LinkedList is a "class" that you've added functionality to using prototype.
What you get back is a JavaScript object.
One way to get around this is to do something like this:
var linkedList = new LinkedList();
var deserializedObject = JSON.parse(jsonString);
linkedList.Items = deserializedObject.Items;
Basically, you'd have to copy over all the state from your deserialized object into your linkedList variable.