How to get dynamic object properties - json

I'm receiving a Json object from a request and I would like to Iterate over its properties and do something like:
if property is equals to "EN" than get it's value.
The solutions That I saw in the web are all related with GetProperties/GetProperty methods but I tried both and none of them worked.
This should be something "simple" but I think that I'm missing something here.
//Deserializing the object
ExpandoObject deserializedContent = JsonConvert.DeserializeObject<ExpandoObject>(obj.ToString(), new ExpandoObjectConverter());
dynamic deserializedDynamicContent = deserializedContent;
//Tries
var value = deserializedDynamicContent.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
var value = deserializedDynamicContent.GetType().GetProperty("ES").GetValue();
in both cases I get zero properties.
I can only get the values if I do the code below, but this will obly me to code if a new language is added.
deserializedDynamicContent.EN,
deserializedDynamicContent.ES or
deserializedDynamicContent.PT
What Am I doing wrong here?
{
"EN":[{"Id":1,"Name":"One"},{"Id":2,"Name":"Two"},{"Id":3,"Name":"Tree"}],
"ES":[{"Id":1,"Name":"Uno"},{"Id":2,"Name":"Dos"},{"Id":3,"Name":"Tres"}],
"PT":[{"Id":1,"Name":"Um"},{"Id":2,"Name":"Dois"},{"Id":3,"Name":"TrĂªs"}]
}

I'm not sure exactly what you're trying to achieve, but since ExpandoObject implements IDictionary<string,object> you should be able to do something like this:
var expando = JsonConvert.DeserializeObject<ExpandoObject>(yourJson);
var dict = (IDictionary<string, object>)expando;
// look for a particular key...
object value;
if (dict.TryGetValue("EN", out value))
{
Console.WriteLine("Key exists!");
var list = (List<dynamic>)value;
Console.WriteLine(string.Join(",", list.Select(x => "{" + x.Id + "," + x.Name + "}")));
}
// or enumerate the entire dictionary...
foreach (var kvp in dict)
{
var list = (List<dynamic>)kvp.Value;
Console.WriteLine(
kvp.Key + ":" + string.Join(",", list.Select(x => "{" + x.Id + "," + x.Name + "}")));
}

Related

MVC - model to a json object

I had a mvc object as my model.
I need to stringfiy my model as a json object type - and then use it in js as i please.
i currently doing something like this
<script type="text/javascript">
$(function () {
var jsonData2 = '#Html.Raw(Json.Encode(Model))';
showBeginDate(jsonData2);
});
</script>
But when i try to acess a json property for exemple as jsonData2.BeginDate I keep getting undefined.
jsonData2 is a json object - why can i "read" from it?
Regards
#riteshmeher 's suggestion is correct
var text = '#Html.Raw(Json.Encode(Model))';
var obj = JSON.parse(text);
I don't know your model so I created a simple model with 2 attributes: Id and Name. In case that the model is a list, you can read it:
// Access to object in position 1
var result = obj[0].Id + " - " + obj[0].Name;
In other case, access right to the property.
var result = obj.Id + " - " + obj.Name;
For more info, check this post:
http://www.w3schools.com/js/js_properties.asp
http://www.w3schools.com/json/tryit.asp?filename=tryjson_parse
UPDATE
like #Stephen Muecke said, better this:
var obj = #Html.Raw(Json.Encode(Model));
var result = obj[0].Id + " - " + obj[0].Name;
thank #Craig for the corrections

Sorted Object/Map in AS3 Flex?

Is it possible to sort an object or have some sort of order in an object in Actionscript 3 Flex? I have an object which is created like so:
private var data:Object = new Object();
I then go on to put some keys and values into it:
this.data.someKeyOne = 0;
this.data.someKeyTwo = 1337;
this.data.someKeyThree = 123;
After that I loop through the object:
for (var dataPart:String in this.data) {
trace("Key: " + dataPart = " Value:" + this.data["dataPart"]);
}
But my issue is that the data will not be displayed in the order I initialized them in. This is frustrating as it is required to be in the order initialized.
As #helloflash said in his answer about loop through an object, and according to Adobe's definition of associative array (which is an instance of the Object class) :
An associative array, sometimes called a hash or map, uses keys instead of a numeric index to organize stored values. Each key in an associative array is a unique string that is used to access a stored value. An associative array is an instance of the Object class, which means that each key corresponds to a property name. Associative arrays are unordered collections of key and value pairs. Your code should not expect the keys of an associative array to be in a specific order.
The behavior that you got is normal and you can not get ordered keys in your case (using an Object like that).
If you don't need keys, you can do as #helloflash said in his answer, using a simple Array or Vector. Otherwise you can use an Array of objects, like this :
var obj:Object, i:int, s:String;
var data_array:Array = [
{key: 'someKeyOne', value: 0},
{key: 'someKeyTwo', value: 1337},
{key: 'someKeyThree', value: 123}
]
for(i = 0; i < data_array.length; i++){
obj = data_array[i];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for (s in data_array) {
obj = data_array[s];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for each (obj in data_array){
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
// all these 3 loops give :
// Key : someKeyOne, Value = 0
// Key : someKeyTwo, Value = 1337
// Key : someKeyThree, Value = 123
Or you can use Object and then sort it into an Array like this :
var data_object:Object = new Object();
data_object.someKeyOne = {index:0, value: 0};
data_object.someKeyTwo = {index:1, value: 1337};
data_object.someKeyThree = {index:2, value: 123};
var tmp_array:Array = sort_obj(data_object);
for(i = 0; i < tmp_array.length; i++){
obj = tmp_array[i];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for (obj in tmp_array) {
obj = tmp_array[obj];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for each (obj in tmp_array){
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
function sort_obj(obj:Object):Array {
var a:Array = [];
for (var key:String in obj) {
a.push({key: key, index: obj[key].index, value: obj[key].value});
}
a.sortOn('index', Array.NUMERIC);
return a;
}
// all these 3 loops give :
// Key : someKeyOne, Value = 0
// Key : someKeyTwo, Value = 1337
// Key : someKeyThree, Value = 123
Hope all that can help you.
Adobe help about looping:
The for..in loop iterates through the properties of an object, or the
elements of an array. For example, you can use a for..in loop to
iterate through the properties of a generic object (object properties
are not kept in any particular order, so properties may appear in a
seemingly random order)
Conclusion
If you want your keys to appear in order, you must use an Array (or a Vector):
var myArray:Array = [0, 1337, 123];
for (var i:String in myArray) {
trace(myArray[i]);
}
// output: 0, 1337, 123

How to access name of key in dynamically created json in action script 3

I have a json object coming from my java code as string :
{
"ABC":["ABC","XYZ","pqr"],
"OMG":["ABC","XYZ","pqr"],
"Hello":["ABC","XYZ","pqr"]
}
on decoding it as
myObj : Object = JSON.decode(result);
Now how do I access key names like ABC, OMG, HELLO...??
Try this will help you.
When you want properties in object use for-in loop or you want value use foreach statement.
var obj:Object = {
"ABC":["ABC","XYZ","pqr"],
"OMG":["ABC","XYZ","pqr"],
"Hello":["ABC","XYZ","pqr"]
};
var jsonText:String = JSON.stringify(obj);
var jsonObj:Object = JSON.parse(jsonText);
for(var key:String in jsonObj){
Alert.show("Key is"+key + " value is "+ jsonObj[key]);
}
Your case exactly
var myObj:Object = JSON.decode(result);
for(var key:String in myObj){
Alert.show("Key is"+key + " value is "+ myObj[key]);
}

Giving instance names to movieclips added using forEach loop

I am using a forEach loop that adds movieclips to the stage for each node in my XML. How does one give these movieclips unique instance names as their being added in the loop?
Here is my parseList function which contains the forEach loop mentioned and the syntax I'm using which isn't working for me.
private function parseList():void {
//use Number variables to keep track of current x and y properties as list display is generated
var titleField:TextField = TextField(listItem);
var itemY:Number = 503;
var itemX:Number = 0;
var artistTracker:String = Playmaster_Jukebox.currArtist;
var artID = 0;
var albID = 0;
var itemID:Number=0;
for each (var listItemData:XML in mainXML.artist[artID].album[albID].track) {
var listItem:MovieClip = new ListItem(itemTitle);
listContainer.addChild(listItem);
listItem.name = "itemID" + " " + albID + " " + itemID;
itemID++;
listItem.y = itemY;
listItem.x = itemX;
TextField(listItem.listItemTitleField);
itemY += listItem.height + 10;
}
}
I am a beginner with the forEach loop and don't understand it yet so comments are appreciated!
If I understand your question correctly; then you're asking how to store the "listItem" MovieClips as you read them from the XML document.
To do this you're probably going to want to use either an Array or a Map:
Using an Array ie:
var listItemArray:Array = new Array();
for each (var listItemData:XML in mainXML.artist[artID].album[albID].track) {
var listItem:MovieClip = new ListItem(itemTitle);
listContainer.addChild(listItem);
listItemArray.push(listItem);// adds the item to the array
}
Using a Map ie:
var listItemMap:Object = {};
for each (var listItemData:XML in mainXML.artist[artID].album[albID].track) {
var listItem:MovieClip = new ListItem(itemTitle);
listContainer.addChild(listItem);
listItem.name = "itemID" + " " + albID + " " + itemID;
listItemMap[listItem.name];// adds an item by the .name you created for it.
}
The map will allow you too look up the items by the names you've given the different items. ie: listItemMap["name"] would find the element with named "name".
The array will allow you to loop through them in order. ie: listItemArray[0] would find the first element.
It's up to you to decide which would be better for your purposes.

Issue while converting actionscript object into XML

I'm new to flex. I'm trying to convert a complex object into an XML.
I'm facing a problem when i'm trying to traverse through the object. here i'm adding the code snippet.
Creating Employee Object
var result:String = new String();
employeeDept = new EmployeeDept();
employee = new Employee();
employee.employeeId = "56789";
employee.employeeName = "XYZ";
//tempString = tempString + "--- Step n ---";
/*employee.employeeDept.deptId = "2";
employee.employeeDept.deptName = "APPLE";*/
employeeDept=new EmployeeDept();
employeeDept.deptId = "3";
employeeDept.deptName = "MS";
employee.employeeDept.addItem(employeeDept);
employeeDept=new EmployeeDept();
employeeDept.deptId = "2";
employeeDept.deptName = "APPLE";
employee.employeeDept.addItem(employeeDept);
empCollection.addItem(employee);
Calling converter method on employee object
recursive(employee, "ShopServiceLifeCycleArtifacts");
Converter method
public function recursive(obj:Object, str:String):String
{
try
{
var xml:XML=new XML('<' + str + '></' + str + '>' );
if(obj is Array && obj.length!=0)
{ //tempString = tempString + "--- Recursive IF Loop---" + obj.length;
var ac:ArrayCollection=new ArrayCollection(obj as Array);
var xml2:XML=new XML(<dept></dept>);
for (var i:Number=0; i<ac.length; i++)
{
var myObj:Object=ac.getItemAt(i);
for (var prop:String in myObj)
{
xml2.appendChild(new XML("<" + prop + ">" + myObj[prop] + "</" + prop + ">"));
}
}
xml.appendChild(xml2);
} else {
if (obj==null)
tempString = tempString + "--- Obj is null ---";
else
{
tempString = tempString + "--- Obj is not null ---";
}
for (var property:String in obj)
{
tempString = tempString + property;
if(obj[property] is Array)
{
tempString = tempString + "--- obj[property] is Array---";
xml.appendChild(recursive(obj[property] as Array, property));
} else {
tempString = tempString + "--- obj[property] is not Array---";
xml.appendChild(XML("<" + property + ">" + obj[property].toString() + "</" + property + ">"));
}
}
}
}catch(e:Error)
{
return tempString+"----------"+e.message;
}
tempString = tempString +xml.toString();
return xml.toString();
}
}
But the issue now is, my employee object is not an array so it will go to else block. I'm check whether the object is null. Object is not null.
I'm going to next step i.e. for loop
for (var property:String in obj){
here comes the issue. Its not going into this for loop & returning null. :(
instead of creating employee object in an action script file & geting a instance of that employee in here if i declare & define an employeeName object here only then the logic is working. i will show that code also.
else {
//tempString = tempString + "--- Recursive Else Loop---";
var employeeNew:Object = {employeeId:"123", employeeName:"San Francisco",
empDept :[{empDeptId:"12345", empDeptName:"XYZ"},{empDeptId:"54568", empDeptName:"ABC"}]};
for (var prop:String in employeeNew) {
//trace("myObject."+prop+" = "+employeeNew[prop]);
if(employeeNew[prop] is Array)
{
xml.appendChild(recursive(employeeNew[prop] as Array, prop));
} else {
tempString = tempString + "--- obj[property] is not Array---";
xml.appendChild(XML("<" + prop + ">" + employeeNew[prop].toString() + "</" + prop + ">"));
}
}
If i use this object its able to convert it into XML. Plz do let me know what is the mistake i'm doing here because of which i'm not able to traverse through the object.
Thanks in Advance.
The for ... in loop only works on dynamic properties of objects. A dynamic property is one that can be added to the object/class at run time.
Your second approach works because you are iterating over an actual Object to which you have added properties to.
The first example does not work because you are iterating over an Employee object. The employee class is not marked as dynamic, and therefore it you cannot add additional properties to it. Even if you made it dynamic (which has a performance impact), it would only iterate over the additional properties that you added at run time, not the properties you define in the class.
One solution to this type of problem is to use describeType():
looping through object property names in actionscript
http://www.actionscript.org/forums/showthread.php3?t=183820