add an array to a specific dictionary object - arrays

So I'm working on a dictionary to build a json schema.
Using a recursive function which works pretty well when appending properties to these objects.
However, I want to add an array to the object properties.
So for this I've attached the following code as an example:
import json
dataProp = (
['airplane', 'fly'],
['car', 'drive'],
['boat', 'sail'],
['airplane', 'pilot'],
['car', 'driver'],
['boat', 'sailer']
)
dataReqProp = (
['airplane', 'fly'],
['boat', 'sail'],
['car', 'driver'],
['boat', 'sailer']
)
obj = {'transportation': {'airplane': {}, 'car': {}, 'boat': {}}}
def update_panel_json(obj, target_key, update_value, json_type):
if isinstance(obj, dict):
for key, value in obj.items():
if key == target_key:
obj[key].setdefault(json_type, {}).update(update_value)
update_panel_json(value, target_key, update_value, json_type)
elif isinstance(obj, list):
for entity in obj:
update_panel_json(entity, target_key, update_value, json_type)
for key, prop in dataProp:
new_prop = {prop: {"type": "string"}}
json_type = 'properties'
update_panel_json(obj, key, new_prop, json_type)
for key, prop in dataReqProp:
new_prop = {prop}
json_type = 'required'
update_panel_json(obj, key, new_prop, json_type)
# obj['transportation']['airplane']['required'] = ['test', 'test2','test3']
#Format dictionary to JSON format
jsonSchema = json.dumps(obj)
pretty_json = json.loads(jsonSchema)
print (json.dumps(pretty_json, indent=2))
In the code there are two arrays.
The first array results in a list of objects in the dictionary.
The second array contains the same objects but with only required properties.
When doing this in the example I get the following error:
ValueError: dictionary update sequence element #0 has length 3; 2 is required
I know that this has something to do with giving more than one value to the update function of the array.
However I want to get something like this:
in the required object for each separate object:
airplane object
"required": ["fly"]
boat object
"required": ["sail"]
and so on
In case there are more properties required for one object it should be added to this same array. For instance
boat object
"required": ["sail","row"]
How do I resolve this error issue?

Related

How to extract values of specific key inside list of JSON dictionaries

Hi I have a json file "groups" with below format and I need to list all the values of key "groupId".
{
'accountId': '1234',
'accountName': 'ABCD',
'groups': {
'items': [{
'groupName': 'groupA',
'groupId': 'grp_111',
'parentGroupId': 'grp_567',
'contractIds': ['ctr_567']
}, {
'groupName': 'groupB',
'groupId': 'grp_222',
'parentGroupId': 'grp_567',
'contractIds': ['ctr_567']
}
I tried below code
result = session.get(urljoin(baseurl, path), headers=headers, verify=False)
groups = result.json()
print (groups['groups'])
for i in groups['items']:
for groupId in i:
print ('groupId')
but getting KeyError: 'items'
I'm expecting to see a list of all the groupIds or it could be in key-value format.
You're getting a KeyError because your top-level dictionary does not have an items key. It has a groups key, which in turn has an items key:
for i in groups['groups']['items']:
Within that loop, i will be a dictionary so you don't need another for loop; you just need:
for i in groups['groups']['items']:
print(i['groupId'])
If you just want a list of group ids, you could write:
groupids = [group['groupId'] for group in groups['groups']['items']]
This would result in groupids containing the value ['grp_111', 'grp_222'].

How prevent Object.keys() sort?

The problem with the ECMA standard for sort of Object.keys() is known:
Object.keys() handle all keys with integer (example: 168), including integer as strings (example: "168"), as a integer. The result is, both are the same (168 === "168"), and overwrite itself.
var object = {};
object["168"] = 'x';
object[168] = 'y';
Object.keys(object); // Array [ "168" ]
object[Object.keys(object)]; // "y"
Interestingly, all keys (including pure integer keys) are returned as a string.
The ecma262 wrote about this: All keys will be handle as a integer, expect the key is a String but is not an array index.
https://tc39.es/ecma262/#sec-ordinaryownpropertykeys
That should tell us: 168 === "168". A toString() do not solve the problem.
var object = {};
object[[3].toString()] = 'z';
object[[1].toString()] = 'x';
object[[2].toString()] = 'y';
Object.keys(object);
// Array(3) [ "1", "2", "3" ]
Paradoxically, in this case, only integer apply as "enumerable" (it's ignoring array.sort(), that sort also strings with letters.).
My question about this is simple: How can i prevent the sort function in Object.keys()? I have testet the Object.defineProperties(object, 1, {value: "a", enumerable: true/false}), but that mean not realy enumerable in the case of integer or string or integer-like string. It means only should it be counted with or not. It means "counted" like omit (if it false), not "enumerabled" like ascending or descending.
A answere like that is not a good answer: Please use only letters [a-zA-Z] or leastwise a letter at the first position of keyword.
What I want: That the keys are not sorted, but output in the order in which they were entered, whether integer, string or symbol.
Disclaimer: Please solutions only in JavaScript.
Javascript Objects are unordered by their nature. If you need an ordered object-like variable I would suggest using a map.
To achieve what you're looking for with a map instead of object you'd do something like the below:
var map1 = new Map();
map1.set("123", "c");
map1.set(123, "b");
var iterator1 = map1.keys();
var myarray = [];
for (var i = 0; i < map1.size; i++) {
myarray.push(iterator1.next().value);
}
console.log(myarray);
// Array ["123", 123]
Unfortunately it's not compatible with IE and I'm not sure how else you could achieve what you need without it. A quick Google did return something about jQuery maps, though.
If you don't want to use jQuery and still need to support IE some points are below:
Is there anything stopping you using an array rather than JS object to store the data you need? This will retain the order per your requirements unlike objects. You could have an object entry in each iteration which represents the key then use a traditional foreach to obtain them as an array. I.e.
The array:
var test_array = [
{key: 123, value: 'a value here'},
{key: "123", value: 'another value here'}
];
// console.log(test_array);
Getting the keys:
var test_array_keys = [];
test_array.forEach(function(obj) { test_array_keys.push(obj['key']); } );
// console.log(test_array_keys);
Then if you needed to check whether the key exists before adding a new entry (to prevent duplicates) you could do:
function key_exists(key, array)
{
return array.indexOf(key) !== -1;
}
if(key_exists('12345', test_array_keys))
{
// won't get here, this is just for example
console.log('Key 12345 exists in array');
}
else if(key_exists('123', test_array_keys))
{
console.log('Key 123 exists in array');
}
Would that work? If not then the only other suggestion would be keeping a separate array alongside the object which tracks the keys and is updated when an entry is added or removed to/from the object.
Object Keys sorted and store in array
First Creating student Object. then sort by key in object,last keys to store in array
const student={tamil:100, english:55, sci:85,soc:57}
const sortobj =Object.fromEntries(Object.entries(student).sort())
console.log(Object.keys(sortobj))
use map instead of an object.
let map = new Map()
map.set("a", 5)
map.set("d", 6)
map.set("b", 12)
to sort the keys (for example, to update a chart data)
let newMap = new Map([...map.entries()].sort())
let keys = Array.from(newMap.keys()) // ['a','b','d']
let values = Array.from(newMap.values()) // [5,12,6]

How to push object into an array? in Angular 7

I am pushing an object into an array but cannot do it?
I'm doing it like this
this.passData = this.tribeForm.value;
var id = {"tribe_id": 1}
this.passData.push(id)
This is the value in the tribeForm
I also tried
var id = {tribe_id: 1}
and
this.passData.splice(0,0, id)
and
this.passData = Array.prototype.slice(id)
and
this.passData.concat(id)
but it all ends up with
TypeError: this.passData.push/splice/concat is not a function
The question is not that clear, But I understood you are manipulating form data, value of form data returns an Object, Not an array. Objects in JavaScript are represented as key-value pairs, (or attribute-value) pairs.
Example :
var object = {
name : "Jhon",
grade : 12,
gpa : 8.12
}
It is just a collection of key-value pairs, push(), concat() and other methods are supported only for Arrays not for Objects. You can achieve whatever you want simply by creating a new key/attribute and assigning the value to it.
this.passData = this.tribeForm.value
this.passData['tribe_id'] = 1
//or, Objects can also contain nested object
this.passData['someKey'] = {'tribe_id' : 1}
You can create an empty array and push objects to it
Example :
var exampleArray = []
exampleArray.push({'tribe_id' : 1})
Now, it works because exampleArray is an Array not JS object.
Thanks for A2A
First, you need to understand the error:
TypeError: this.passData.push/splice/concat is not a function
Push/splice/concat is functions for Array and because of that the console is yelling at you that the passData is not an Array.
Make sure your passData is an Array and you will able to do so.

Get field names and values from LablelledGenerics of a case class

I try to have Seq[String], containing the fields name of a case class
And another Seq[String] containing values of case class.
In a generic way. I think I will have to map values with a Poly1 function to have the Arbitrary type => String.
But now, I'm not able to extract keys and values form LabelledGenerics.
def apply[T,R <: HList](value : T)(implicit gen: LabelledGeneric.Aux[T, R],
keys : Keys[R],
valuesR : Values[R]
) {
val hl = gen.to(value)
val keys = hl.keys ...
val values = hl.values.map ...
}
I'm not sure if I have to ask for keys and values implicit or if it's possible to have this from the LabelledGeneric.
I have tried to map the following Poly over keys to have a hlist of string.
But it's seems keys are not Witness
object PolyWitnesToString extends Poly1 {
implicit def witnessCase = at[Witness]{ w => w.toString}
}
I'm a little bit lost now.

Drools - Rule to check whether an array does not contain object with only certain properties

I am trying to write a Drools rule to identify whether an array of items contains an item that the user has selected.
My session looks similar to the following (admittedly this is simplified but the concept is the same):
data = {
items=[
{
prop1=1,
prop2=2,
prop4=4
}
],
selectedItem={
prop1=1,
prop2=2
prop3=3
}
}
The data is converted from JSON into HashMaps and ArrayLists - where data is a HashMap, items is an ArrayList of HashMaps and selectedItem is an HashMap.
Basically, I want the rule to fire only when the items array does not contain an Map that resembles selectedItem. By "resembles", I mean that prop1 and prop2 are the same.
Is this possible with Drools?
I have tried:
when
Map( data.items not contains Map( prop1 == data.selectedItem.prop1, prop2 == data.selectedItem.prop2 ) )
then
// do something
But this returns:
Description Resource Path Location Type
BuildError: Unable to Analyse Expression !( data.items contains Map( prop1 == data.selectedItem.prop1, prop2 == data.selectedItem.prop2 ) ):
java.lang.Class cannot be cast to org.mvel2.util.MethodStub

Resources