Changing a JSON object parsed with APEX_JSON - plsql

I would like to be able to change a JSON object parsed with the APEX_JSON.parse() function, but I found nothing in the official documentation, no tips or examples about that.
In the code below I putted comments in the specific points in order to give a clear idea about my need.
SET SERVEROUTPUT ON
DECLARE
j apex_json.t_values;
l_paths apex_t_varchar2;
writers clob;
json_object_result clob;
BEGIN
writers := '[
{
"id": null,
"hashCode": "7ef605fc8dba5425d6965fbd4c8fbe1f",
"description": "Machado de Assis",
"base64Img": "8eNZ28Dh5rZQIPhNEfwqoo1LCVx..."
},
{
"id": 151,
"hashCode": "a8f15eda80c50adb0e71943adc8015cf",
"description": "José Alencar",
"base64Img": "/XIQIHCol8eNZ28Dh5rZQIPhNEfwqoo1LCVx/9k=..."
}
]';
apex_json.parse(j, writers);
l_paths := apex_json.find_paths_like (
p_values => j,
p_return_path => '[%]',
p_subpath => '.hashCode',
p_value => '7ef605fc8dba5425d6965fbd4c8fbe1f'
);
dbms_output.put_line('Itens found: ' || l_paths.count);
if (l_paths.count = 1) then
dbms_output.put_line('id: ' || apex_json.get_varchar2(p_values => j, p_path => l_paths(1) || '.id'));
dbms_output.put_line('hashCode: ' || apex_json.get_varchar2(p_values => j, p_path => l_paths(1) || '.hashCode'));
dbms_output.put_line('description: ' || apex_json.get_varchar2(p_values => j, p_path => l_paths(1) || '.description'));
dbms_output.put_line('base64Img: ' || apex_json.get_varchar2(p_values => j, p_path => l_paths(1) || '.base64Img'));
-- Here I would like to nullify base64Img attribute value
json_object_result := 'here goes the object matched in the search with the base64Img attribute value null';
end if;
END;
In my json_object_result variable I would like to save the JSON object matched in the apex_json.find_paths_like() with its base64Img attribute null. In my example the result would be
{
"id": null,
"hashCode": "7ef605fc8dba5425d6965fbd4c8fbe1f",
"description": "Machado de Assis",
"base64Img": ""
}
or
{
"id": null,
"hashCode": "7ef605fc8dba5425d6965fbd4c8fbe1f",
"description": "Machado de Assis"
}
Is it possible to make something like that with APEX_JSON?

Related

Add values to a JSON array if outer array's name == 'something'

I'm passing a JSON object to jq and want to add extra objects to an inner array ('accessories') if its parent array ('platforms') matches a certain name.
Here's my source JSON:
{
"bridge": {
"name": "Homebridge",
"port": 51395
},
"accessories": [],
"platforms": [
{
"name": "Config",
"port": 8581,
"platform": "config"
},
{
"platform": "homebridge-cbus.CBus",
"name": "CBus",
"client_ip_address": "127.0.0.1",
"accessories": [
{
"values": "existing"
}
]
}
]
}
This works beautifully:
jq '.platforms[1].accessories += [{ "values" : "NEW" }]'
... but of course it's poor form to expect platforms[1] to always the be array I want to append to, so I set about trying to form the right syntax for a search or if/then/else to only act on the .name of the appropriate one.
I thought this was my solution:
jq '.platforms[] | if ( .name=="CBus" ) then .accessories += [{ "values" : "NEW" }] else . end'
... until I realised it was only passing the 'platforms' through and eating the 'bridge' object and empty outer 'accessories' array, which I need to retain.
My issue looks to be similar to JQ | Updating array element selected by `select`, but I've tried LOTS of combinations but just can't break through.
Edit: Here's the correct JQPlay I've been working with:
https://jqplay.org/s/dGDswqAEte
Thanks for any help.
That's a good attempt. The key here is to use the select() function to identify the object you are going to update and overwrite the overall array using |= operator, i.e.
.platforms |= ( map(select(.name == "CBus").accessories += [{ "values" : "NEW" }] ) )
For the snippet in your jq-play link (now removed), you need to do
.gcp_price_list."CP-COMPUTEENGINE-OS"
|= with_entries(select(.value.cores == "shared").value.cores = "0.5")
Or if you want to be even more specific, and keep the entry in gcp_price_list configurable, do
.gcp_price_list |=
with_entries (
select(.key == "CP-COMPUTEENGINE-OS").value |=
with_entries(
select(.value.cores == "shared").value.cores = "0.5") )

Whats the correct key/value Syntax to convert this Array with Symfony/XmlEncoder?

im building my request data as an array structure and want to use the symfony XmlEncoder to encode my Array to XML.
so i guess i got the fundamental part right, it looks like that for example:
$request_object = [
"acc-id" => $all_credentials,
"req-id" => $request_guid,
"tran-type" => "spec-url"
];
the syntax im looking for encodes in the following format, with attribute and value:
<amount currency="EUR">1.99</amount>
i have the possiblity to use the # sign on an array key, but how to also fit in the value?
$request_object = [
"acc-id" => $all_credentials,
"req-id" => $request_guid,
"tran-type" => "spec-url"
"am" => ["#attr"=>"attrval"]
];
this should be
<am attr="attrval"/>
but how to write it that i can also set the value? like:
<am attr="attrval">VALUE</am>
help is much appreciated
Use '#' as the index for the scalar value.
I found it by looking through the tests for the encoder.
#src:https://github.com/symfony/serializer/blob/master/Tests/Encoder/XmlEncoderTest.php
#line: 196
public function testEncodeScalarRootAttributes()
{
$array = [
'#' => 'Paul',
'#eye-color' => 'brown',
];
$expected = '<?xml version="1.0"?>'."\n".
'<response eye-color="brown">Paul</response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
}
...
#line: 234
public function testEncodeScalarWithAttribute()
{
$array = [
'person' => ['#eye-color' => 'brown', '#' => 'Peter'],
];
$expected = '<?xml version="1.0"?>'."\n".
'<response><person eye-color="brown">Peter</person></response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
}

Immutable remove item from array from all elements in Map | Redux state

I am facing some problems removing an items from an array from every element within a map in my Redux state.
Using the following structure
entities: {
brands: (Map) {
first: {
...props,
strategists: [
'1', '2'
]
},
second: {
...props,
strategists: [
'1', '2'
]
}, ..
}
}
This is the best I could do:
const newBrands = state
.get('brands')
.map(brand => brand.updateIn(['strategists'], strategists => strategists.filter(s => s !== id)))
return state.set(['brands'], newBrands)
I doesn't add up tho and I coudn't really find it online either.
Thanks
I had not used Immutable.js before, but I played around with your code example and everything seems to work as expected up until the last line, where you're setting state using state.set(['brands'], newBrands) instead of state.set('brands', newBrands); Could that have been the issue? Otherwise the only change is that I assumed that the first and second should also be Maps, so if you got an error before then maybe that was also part of the problem.
I included the code just in case:
const state = Immutable.Map({});
const original = Immutable.Map({
first: Immutable.Map({
someProp: 'someValue1',
strategists: [
'1', '2', '3'
]
}),
second: Immutable.Map({
someProp: 'someValue2',
strategists: [
'1', '2', '3'
]
})
});
const id ='2';
const brands = original
.map(brand =>
brand.updateIn(['strategists'], strategists =>
strategists.filter(s => s !== id)
)
);
const newState = state.set('brands', brands);
console.log(
newState.get('brands')
.toString()
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

Checking absence of attribute with cts:query

I have an XML fragment where I want to have different queries based in the existence of the id attribute:
<author order="1"
id="99999999"
initials="A."
given-names="Able"
surname="Baker"
fullname="Able Baker"/>
I have tried:
let $first-query := if ($first)
then cts:or-query((
cts:element-attribute-word-match(xs:QName("author"), xs:QName("given-names"), $first || "*", ("collation=http://marklogic.com/collation/codepoint")),
cts:element-attribute-word-match(xs:QName("author"), xs:QName("initials"), $first || "*", ("collation=http://marklogic.com/collation/codepoint"))
))
else ()
let $last-query := if ($last)
then cts:element-attribute-word-match(xs:QName("author"), xs:QName("surname"), $last || "*", ("collation=http://marklogic.com/collation/codepoint"))
else ()
let $author-no-id-query :=
cts:and-query((
cts:not-query(
cts:element-attribute-value-query(xs:QName("author"), xs:QName("id"), "*")
),
$first-query,
$last-query
))
let $query := cts:element-query(xs:QName("author"),
cts:or-query(($author-no-id-query, $author-id-query
)))
If the id exists, then a different query takes place and a match against the id occurs. How do I detect an absence of an attribute in MarkLogic?
I have inserted two test documents into the database:
xdmp:document-insert('/example.xml', <author order="1"
id="99999999"
initials="A."
given-names="Able"
surname="Baker"
fullname="Able Baker"/>)
xdmp:document-insert('/example2.xml', <author order="1"
initials="A."
given-names="Able"
surname="Baker"
fullname="Able Baker"/>)
And run the following query against these documents:
cts:search(fn:doc(),
cts:element-query(xs:QName('author'), cts:and-query((
cts:not-query(cts:element-attribute-value-query(xs:QName('author'), xs:QName('id'), '*', ("wildcarded")))
)
)))
This search only matches the document where the ID attribute does not exist.

Meteor aldeed collections2 update data to array of objects using for loop

Hello Now i have a problem. I want to insert data to array of objects using for loop
fields:{
type:[Object],
label:"Fields",
optional:true
},
"fields.$.category":{
type:String,
label: "Category"
},
"fields.$.sub":{
type:String,
label:"Sub Category",
},
And using savaData.js in server i tried
// ServiceProviders.update({
// '_id':"GmkGSXjyNFshomdCu"},
// {
// '$set': {'fields':{
// '$.category':categorydata,
// '$.sub':subdata
// }}
// },function(error,result){console.log(error);console.log(x+y);});
and
ServiceProviders.update(
{'_id': 'JN4mRPfJZqBadZtPY' },
{'$set': {'fields.0.category': categorydata,'fields.0.sub':subdata}},
true );
then
var x = "fields."+i+".category";
var y = "fields."+i+".sub";
x=x.toString();
y=y.toString();
ServiceProviders.update(
{'_id': 'JN4mRPfJZqBadZtPY' },
{'$set': {x: categorydata,y:subdata}},
true );
I got Different errors every time could you please help me in this issue
Currently, $ Does not work on Meteor js.
So you have to create a fields object on either server side or client side:
var fieldsData = []
for (var i = 0; i < categorydata.length || i < subdata.length ; i++ ){
fieldsData.push({
category : ( categorydata[i] ? categorydata[i] : '' ),
sub : ( subdata[i] ? subdata[i] : '' )
})
}
ServiceProviders.update(
{'_id': 'JN4mRPfJZqBadZtPY' },
{'$set': {fields : fieldsData}},
true );
Please make sure for either every filds data have cat and subcat value or make cat and subcat cat optional true.

Resources