Reducing null check in free marker templete - freemarker

I have json:
{"getKycBusinessDetailsResponse":
{"ADDRESS":
{"fieldDataResponse":
{ "dataValue":
{"__type": "com.amazon.skies#AddressData",
"addressId": "2BH6RKV6KLU4OAFIQGOEG12IX7FW7W7I6A2H6I7W7WF7XILPXTQ2EIA2OX4BY72H"},
"isEditable": false,
"isMandatory": false,
"isUpdateRequired": false},
"fieldDocumentsResponse":
{"documentValue":
{},
"isMandatory": false,
"isUpdateRequired": false}
}
}
}
I want extract the addressId value from the above Json and this what I have done:
<#if getKYCBusinessData??>
<#assign getKYCBusinessData = (getKYCBusinessData)?eval>
<#if getKYCBusinessData.getKycBusinessDetailsResponse?? && getKYCBusinessData.getKycBusinessDetailsResponse?has_content>
<#assign businessDetails = getKYCBusinessData.getKycBusinessDetailsResponse>
<#if businessDetails.ADDRESS?? && businessDetails.ADDRESS?has_content>
<#assign ADDRESS = businessDetails.ADDRESS>
<#if ADDRESS.fieldDataResponse?? && ADDRESS.fieldDataResponse?has_content>
<#assign fieldDataResponse = ADDRESS.fieldDataResponse>
<#if fieldDataResponse.dataValue?? && fieldDataResponse.dataValue?has_content>
<#assign dataValue = fieldDataResponse.dataValue>
<#if dataValue.addressId?? && dataValue.addressId?has_content>
<#assign addressId = dataValue.addressId>
{
"addressId" : "${addressId}"
}
</#if>
</#if>
</#if>
</#if>
</#if>
</#if>
As you can see here to extract the address id there are multiple null check need to apply. How do reduce the number of null check here?

They key is to know about the (...)! construct, which makes an [] (and also an "" and false on the same time, but we don't utilize that) out of the expression inside, if that fails due to a missing variable. What makes the solution still verbose is that you only need the { ... } in the output if the thing printed inside it exits. To deal with that, I treat the result as a list that's either 0 or 1 long:
<#list ([ getKYCBusinessData.getKycBusinessDetailsResponse.ADDRESS
.fieldDataResponse.dataValue.addressId ])! as it>
{
"addressId": "${it}"
}
</#list>
Another approach is to #assign and do an #if, however, it can't tell the difference between a value that was truly missing, and a value that was there but had a value like "":
<#assign opt = (getKYCBusinessData.getKycBusinessDetailsResponse.ADDRESS
.fieldDataResponse.dataValue.addressId)!>
<#if opt?has_content>
{
"addressId": "${opt}"
}
</#if>

Related

Logstash filter out values with null values for a key in a nested json array

I have quite an extensive Logstash pipeline ending in a Json as such:
{
"keyA": 1,
"keyB": "sample",
"arrayKey": [
{
"key": "data"
},
{
"key": null
}
]
}
What I want to achieve is to filter "arrayKey" and remove objects within with value for "key" is null.
Tried this to no luck:
filter {
ruby {
code => "
event.get('arrayKey').each do |key|
[key].delete_if do |keyCandidate|
if [keyCandidate][key] != nil
true
end
end
end
"
}
}
This gives no implicit converter found from |hash|:|Int| error. How do I achieve this? Is there and easier way to do this?
As Aleksei pointed out, you can create a copy of the array that does not contain entries where [key] is null using reject. You have to use event.set to overwrite the inital value of [arrayKey]
ruby {
code => '
a = event.get("arrayKey")
if a
event.set("arrayKey", a.reject { |x| x["key"] == nil })
end
'
}

Criteria Builder query LIKE in json field

I am trying to build a query with Criteria Builder(LIKE), to look for a string in JSONARRAY field like this:
[
{
"family_class": "Electric",
"family_name": "lightBulb"
},
{
"family_class": "Others",
"family_name": "Oil"
}
]
one option would be to look for the family_name attribute, or maybe check if it contains the string there.
if (residues != null && residues.length > 0) {
List<Predicate> predicates = new ArrayList<Predicate>();
for (String residue : residues) {
predicates.add(cb.like(root.get("jsonColumn"), residue.toLowerCase()));
}
cr.select(root).where(predicates.toArray(new Predicate[] {}));
Query<SyncCollectionPoints> q = sess.createQuery(cr);
List<SyncCollectionPoints> result= q.getResultList();
This is the error i get:
Unrecognized token 'oil': was expecting ('true', 'false' or 'null')
All i want is to return the lines that have that string in the jsonColumn field.
I got it to work like this:
#Formula(value = "lower(jsonColumn::text)")
private String residuesToSearch;
just a simple cast did the trick

Looping N size nested array

I have nested array and I need to loop second level deep nested array and do some match.
Loop friends array and compare reqs_status where user_id is the loggedin user ($id).
Json array shown below:
[
{
"id":8,
"firstname":"Lauren",
"lastname":"Lambie",
"email":"lal30#org.uk",
"role":1,
"photo":"uploads\/5.jpg",
"bio":"Surfer, follower of Christ, band member and Swiss design-head.",
"friends":[
{
"id":8,
"user_id":9,
"friend_id":8,
"reqs_status":2,
"created_at":null,
"updated_at":null
}
]
},
{
"id":23,
"firstname":"Jar",
"lastname":"Morrison",
"email":"jm93#org.uk",
"role":1,
"photo":"uploads\/20.jpg",
"bio":"Operating at the crossroads of beauty and intellectual purity.",
"friends":[
{
"id":21,
"user_id":22,
"friend_id":23,
"reqs_status":2,
"created_at":null,
"updated_at":null
},
{
"id":28,
"user_id":21,
"friend_id":23,
"reqs_status":0,
"created_at":null,
"updated_at":null
}
]
}
]
Edit
In My blade view I have :
#if ($user['friend'][0]['reqs_status'] == 1)
//do something
#elseif($user['friend'][0]['reqs_status'] == 2)
//do something elseif
#else
//do something else
Here I am not aware if [0] or [1], [2],.... is the right number because it is dynamic and the size of array is not fixed. I need a way to loop this nested array.
So I tried to break it into something like:
#foreach ($users['friends'] as $friend)
#if($friend['reqs_status'] == 1)
#elseif($friend['reqs_status'] == 2)
#else
#endforeach
I get error here: Undefined index: friends. so I was thinking how to make it dynamic [0] this part? or fix my code of foreach loop and if condition?

convert locale format back to default with numeral.js

I'm storing the number and currency formats in the default numeral js format. I allow the user to have their own formatting based on their locale setting. I'm trying to figure out how I can convert their custom formatting back to the default formatting in order to store it consistently and in case they change locale.
for example the current is set:
numeral.register('locale', 'fr', {
delimiters: {
thousands: '.',
decimal: ','
},
abbreviations: {
thousand: 'k',
million: 'm',
billion: 'b',
trillion: 't'
},
ordinal : function (number) {
return number === 1 ? 'er' : 'ème';
},
currency: {
symbol: '€'
}
});
When I get '0.0,00€' back as preferred formatting, how can I convert is back to the default numeral.js setting being '0,0.00$' for storage.
You can simply switch between locals by setting the local with numeral.local('en'). You could use a litte helper function to do that for you. You would just have to pass it the desired local and maybe your current numeral you need to be switched.
Here is an example doing exactly that. I have also added money.js to convert between currencies.
I'm sure you will get the idea.
var yourNumeral = numeral(1234.56);
// helper fn to switch local and convert.
function switchLocal(local, num, convert) {
numeral.locale(local);
num.set(fx.convert(num.value(), convert));
return num.format();
}
// set money.js base and rates
fx.base = "EUR";
fx.rates = {
"USD" : 1.0873 // eg. 1 EUR === 1.0873 USD
};
// set default format.
numeral.defaultFormat('0,0[.]00 $');
// load a locale.
numeral.register('locale', 'fr', {
delimiters: {
thousands: ' ',
decimal: ','
},
abbreviations: {
thousand: 'k',
million: 'm',
billion: 'b',
trillion: 't'
},
ordinal : function (number) {
return number === 1 ? 'er' : 'ème';
},
currency: {
symbol: '€'
}
});
// set the loaded local.
numeral.locale('fr');
// yourNumeral with loaded local "fr".
console.log(yourNumeral.format());
// yourNumeral switched local to "en" and converted from € to $.
console.log(switchLocal('en', yourNumeral, { from: "EUR", to: "USD" }));
// yourNumeral switched back to "fr" local and converted back to € from $.
console.log(switchLocal('fr', yourNumeral, { from: "USD", to: "EUR" }));
<script src="https://openexchangerates.github.io/money.js/money.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js"></script>

Pipe filter based on two or more attributes value in Angular2

If I have an array of objects like
[
{name: 'aaa', type: 'A'},
{name: 'aaa', type: 'B'},
....
]
How can I create a filter using pipe inside ngFor expression, something like
*ngFor='let obj of array | filter:name[nameValue]:type[typeValue]
Here, name[nameValue] name is a property, nameValue is its value.
only show the objects which match the nameValue in name property and typeValue in type property simultaneously.
I Want a more generalized filter which takes any property[propertyValue] and can filter output accordingly.
This is a way you could do it. Just give the filter pipe an array of the fields with the values you want to filter it with.
The Pipe:
#Pipe({
name: 'filter',
pure: false
})
export class FilterPipe implements PipeTransform {
transform(values: Array<any>, args:any[]):any {
return values.filter((value) => {
for (let i = 0; i < args.length; i++) {
if (value[args[i][0]] != args[i][1]) {
return false;
}
}
return true;
});
}
}
The code in the template:
<h3>Only Type A:</h3>
<div *ngFor="let elm of arr | filter:[['type', 'A']]">
<span>Name: {{elm.name}}</span> | <span>Type: {{elm.type}}</span>
</div>
<h3>Name bbb and Type B:</h3>
<div *ngFor="let elm of arr | filter:[['type', 'B'], ['name', 'bbb']]">
<span>Name: {{elm.name}}</span> | <span>Type: {{elm.type}}</span>
</div>
Plunker for working example

Resources