Issue when GroupBy an ArrayList object in Kotlin? - java

I have issue when I use GroupBy an ArrayList object in Kotlin.
I have JSON like here:
{
"securityAccountList": [
{
"accountNumber": "001548900001",
"accountName": "Tjandraningrum",
"currency": "IDR",
"debtInstrument": "0",
"equityInstrument": "0"
},
{
"accountNumber": "001548900001",
"accountName": "Tjandraningrum",
"currency": "IDR",
"debtInstrument": "0",
"equityInstrument": "0"
},
{
"accountNumber": "001548900001",
"accountName": "Tjandraningrum",
"currency": "USD",
"debtInstrument": "22",
"equityInstrument": "66"
}
]
}
I generate object by GSON like this:
data class ContentModel(
#SerializedName("securityAccountList") var securityAccountList: ArrayList<SecurityAccountList> = arrayListOf()
)
data class SecurityAccountList(
#SerializedName("accountNumber") var accountNumber: String? = null,
#SerializedName("accountName") var accountName: String? = null,
#SerializedName("currency") var currency: String? = null,
#SerializedName("debtInstrument") var debtInstrument: String? = null,
#SerializedName("equityInstrument") var equityInstrument: String? = null
)
now I want to grouping by field currency and I want result like this
{
"securityAccountList": [
{
"accountNumber": "001548900001",
"accountName": "Tjandraningrum",
"currency": "IDR",
"debtInstrument": "0",
"equityInstrument": "0"
},
{
"accountNumber": "001548900001",
"accountName": "Tjandraningrum",
"currency": "USD",
"debtInstrument": "22",
"equityInstrument": "66"
}
]
}
but the result not changed, still 3 securityAccountList,
this my code for grouping:
val newSecurityAccountList= contentModel.securityAccountList
newSecurityAccountList.groupingBy { it.currency }
newSecurityAccountList.sortBy { it.currency }
Note: contentModel.securityAccountList is ArrayList of object JSON the newSecurityAccountList not changed value.
please your advice, sorry for my English.

private fun List<SecurityAccountList>.customFilter(): List<SecurityAccountList> =
groupBy { it.currency }.map {
// HERE you can do whaterver you need.
it.value
.filter { item-> item.currency >= 0 }
.maxByOrNull { item-> item.accountName.length }
}.filterNotNull()
Using in code
val returnlist = yourListBeforeFilter.customFilter()
For more details tell us what exactly you need.
You can as well use here sortBy

It sounds like you are expecting groupingBy to modify the list. In fact it won't, but will instead return a new Grouping object which can be used to gather the results into a new, different list.
It can be confusing, because sortBy does mutate the list, whereas the similar-looking groupBy and groupingBy functions return a new object or copy and don't mutate the original.
The best way to be sure whether a function is going to mutate the existing object or create a new object is to check its documentation. In Kotlin, most of the standard library functions are non-mutating, because Kotlin encourages immutability.
You could try replacing your code with something like:
val groupedAccounts = contentModel.securityAccountList.groupBy { it.currency }
Note how the variable stores the result of the call to groupBy, not the original securityAccountList.

Related

Using Jackson, how can you get a list of objects from an interesting json?

I have this json, I need to get a list of currency objects using Jackson (the objects itself has a currency name field - "USD", "type" and "show") as a result. How can I do it in a simple and clear way?
Any help would be welcome
{
...
"result": "OK",
"currency": {
"currencies": {
"LB": {
"type": "A",
"setting": {
"show": true,
},
"access" : true
},
"USD": {
"type": "B",
"setting": {
"show": true,
},
"access" : true
},
"RUB": {
"type": "A",
"setting": {
"show": true,
},
"access" : true
},
....
// and more..
},
...
}
}
"currencies": {
"LB": {
"type": "A",
"setting": {
"show": true,
},
"access" : true
},
"USD": {
"type": "B",
"setting": {
"show": true,
},
"access" : true
},
"RUB": {
"type": "A",
"setting": {
"show": true,
},
"access" : true
},
....
// and more..
},
...
This looks like an Map, not a List. Does that help you? So you would need to create Currency class and have jackson parse this structure to Map<String, Currency>. Note that currency will not contain the identifier (like "USD"), only they key in the map will.
You can read your Json as a Map<String, Object>. Once you have the map you iterate through your map and build your List.
If you want to de-serialize (read) from Json to List of your custom objects you need to have your Json restructured to be Json List and not Json Object. Then you can read your Json into a List directly. In any case, there is an Open source Library that has a feature based on Jackson library really simplifies reading/writing objects from/to Json. If you have a json string all you have to do is:
Map<String, Object> map = JsonUtils.readObjectFromJsonString(jsonString, Map.class);
It throws IOException though, so you will need to handle it. Here is the Javadoc. The library is called MgntUtils and could be found as Maven artifact and on the Github (including javadoc and source code)
I was able to add object saving to the list, but in a rather inconvenient way, it seems to me...
ArrayList<Dto> currencyObjectList = new ArrayList<Dto>();
CurrencyStaticDto obj = null;
JsonNode currencies = mapper.readTree(response.getBody()).get("currencies");
Iterator<Map.Entry<String, JsonNode>> fields = currencies.fields();
while(fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
String fieldName = field.getKey();
JsonNode fieldValue = field.getValue();
obj = mapper.readValue(fieldValue.toString(),CurrencyStaticDto.class);
obj.setCurrency(fieldName);
currencyObjectList.add(obj);
}

How to count particular pattern in a string?

we have some requests which have a lot of experiments. I just want to count the no experiments. If it's greater than some number then I will block those requests
{
"context": {
"requestId": "",
"locale": "",
"deviceId": "",
"currency": "",
"memberId": 0,
"cmsOrigin":,
"experiments": {
"forceByVariant":,
"forceByExperiment": [
{
"id": "test",
"variant": "A"
}
]
}
}
In this request, I just want to check how many id and variant inside the forceByExperiment. I have tried to do using regular expression but not able to do it. Anyone do it before similar thing.
I just split the string with variant and count them. Not sure good idea, but the end goal is to figure out that the request have a lot of experiments.
Using the circe library and Scala, here is an easy solution:
import io.circe._, io.circe.parser._
val jsonString = """{
"context": {
"requestId": "",
"locale": "",
"deviceId": "",
"currency": "",
"memberId": 0,
"cmsOrigin": "foo",
"experiments": {
"forceByVariant": [],
"forceByExperiment": [
{
"id": "test",
"variant": "A"
}
]
}
}
}"""
val parseResult = parse(jsonString)
val nElems = for {
json <- parse(jsonString)
array <- json.hcursor.downField("context").downField("experiments").downField("forceByExperiment").as[Seq[Json]]
} yield array.length
println(nElems) // Right(1)
If you really want to use regex, and if there is no id field in your json structure, you can use the following expression "id": "(\w+)" and count the number of match.
Example: https://regex101.com/r/GCeByw/1/

Get json object in Array based on key and value in Java

I have a Json body like the example below. I need to extract the value from a key that has another key with a specific value in an array. I am passing in a JsonNode with everything in the detail component of the message, I can easily extract from each level, however, I'm struggling with the array.
In this case, I need to extract the value of "value" (Police/Fire/Accident Report) from the object in the array which has a key/value pair of "name":"documentTitle". I understand this is a JSONArray, but I can't find a good example that shows me how to extract the values for an object in the array that contains a certain key/value pair, I don't think I can rely on getting the object in position [2] in the array as the same objects may not always be present in the additionalMetadata array.
Sample Json:
"sourceVersion": "1.0",
"eventId": "8d74b892-810a-47c3-882b-6e641fd509eb",
"clientRequestId": "b84f3a7b-03cc-4848-a1e8-3519106c6fcb",
"detail": {
"stack": "corona",
"visibilityIndicator": null,
"documentUid": "b84f3a7b-03cc-4848-a1e8-3519106c6fcb",
"additionalMetadata": [
{
"name": "lastModifiedDate",
"value": "2021-05-21T04:53:53Z"
},
{
"name": "documentName",
"value": "Police/Fire Report, 23850413, 2021-05-20 14:51:23"
},
{
"name": "documentTitle",
"value": "Police/Fire/Accident Report"
},
{
"name": "documentAuthor",
"value": "System Generated"
},
{
"name": "lastModifiedBy",
"value": "System Updated"
},
{
"name": "createdBy",
"value": "System Generated"
},
{
"name": "documentDescription",
"value": "Police/Fire Report received"
},
{
"name": "organizationCode",
"value": "Claims"
}
]
}
}```
Loop through the json array and extract the json object with name documentTitile. From that json object you can get the value
Well, either the JSON framework you're using supports this out of the box (check the documentation) or you could convert it manually to a map:
List<AdditionalMetadataEntry> additionalMetadata;
[...]
Map<String, String> additionalMetadataMap = additionalMetadata.stream().collect(Collectors.toMap(AdditionalMetadataEntry::getName, AdditionalMetadataEntry::getValue));
I was able to figure it out. I created a new node off the existing notificationBody JsonNode, then parsed through the metadata key/value pairs:
String docTitle = "";
JsonNode additionalMetadata = notificationBody.get("detail").get("additionalMetadata");
for (JsonNode node: additionalMetadata) {
String name = node.get("name").asText();
String value = node.get("value").asText();
if(name.equals("documentTitle")){
docTitle = value;
}
}

Save JSON request as Item in dynamoDb

I have a request of the following JSON format:
{
"profile": {
"created": 1505202655,
"createdBy": "abc",
"updated": 1505202655,
"updatedBy": "xyz"
},
"likesId": [
"0010127916"
],
"icon": null,
"Attributes": {
"backgroundColor": "#FFFFFF",
"logo": "images/Logos/P0010127916.jpg",
"textColor": "#000000"
},
"profileId": "PACYG0010916",
"restrictions": {
"clients": [
"Android",
"SmartTv"
],
"UserTypes": [
"user1",
"user2"
],
"periodEnd": 1512978849,
"periodStart": 1505202849
},
}
I am trying to save the above JSON request Object in the dynamoDb table using putItem. However I am stuck in some issues which are as follows:
Can I store this whole JSON request as-is(without escaping double quotes) in the form of item in dynamodb table?
In case of likesId and Attributes I am storing them as a List and Map with the help of .withList and .withMap methods respectively, but in case of profile I have taken it as a POJO which has 4 states, how can I save this object with the putItem as I did not find any method for saving objects like this, as we have methods for string, numbers and other datatypes, how can I save my own object?
Any kind of guidance will be highly appreciated as I am new to dynamoDb and learning it by doing POC.
You should be able to save it quite easily with the DocumentClient class:
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#put-property
var params = {
TableName : 'Table',
Item: item
};
var documentClient = new AWS.DynamoDB.DocumentClient();
documentClient.put(params, function(err, data) {
if (err) console.log(err);
else console.log(data);
});
Where item is the object from your original question

Get sub-array from JSON

I parsing some data from a json file. Here is my JSON File.
[
{
"topic": "Example1",
"contact": [
{
"ref": [
1
],
"corresponding": true,
"name": "XYZ"
},
{
"ref": [
1
],
"name": "ZXY"
},
{
"ref": [
1
],
"name": "ABC"
},
{
"ref": [
1,
2
],
"name":"BCA"
}
] ,
"type": "Presentation"
},
{
"topic": "Example2",
"contact": [
{
"ref": [
1
],
"corresponding": true,
"name": "XYZ"
},
{
"ref": [
1
],
"name": "ZXY"
},
{
"ref": [
1
],
"name": "ABC"
},
{
"ref": [
1,
2
],
"name":"BCA"
}
] ,
"type": "Poster"
}
]
I can fetch and store data one by one. Like this one
JSONArray getContactsArray = new JSONArray(jsonObject.getString("contact"));
for(int a =0 ; a < getContactsArray.length(); a++)
{
JSONObject getJSonObj = (JSONObject)getContactsArray.get(a);
String Name = getJSonObj.getString("name");
}
1)Now, my question is there any way to get all name values for each array with single query.
2) Can I get all those values in an Array ?
Please correct me, if I am doing anything wrong. Thank you.
Iteration cannot be avoided here as org.json and other Json parsers as well provide random access to objects but not to their properties collectively (as a collection). So, you can't query something like "all name properties of all contact objects" unless you probably get a Json parser like Gson to unmarshall it that way.
But, that's too much to just avoid a for loop when you can definitely shorten the parse by making use of the appropriate API methods to avoid unnecessary object casts.
JSONArray contacts = jsonObject.getJSONArray("contact");
String[] contactNames = new String[contacts.length()];
for(int i = 0 ; i < contactNames.length; i++) {
contactNames[i] = contacts.getJSONObject(i).getString("name");
}
Better to use a json parser such as GSon or Jackson to marshall your json to a java object. Then you can write utitlity method in your java class to retrieve all the names in that object.
Try this:
Create JSONObject of your file and try to get array of all names and iterate it to get all values.
public static String[] getNames(JSONObject jo) {
int length = jo.length();
if (length == 0) {
return null;
}
Iterator i = jo.keys();
String[] names = new String[length];
int j = 0;
while (i.hasNext()) {
names[j] = (String) i.next();
j += 1;
}
return names;
}

Categories