I want to delete all versions of an object with a given key using software.amazon.awssdk.s3 v2.
So far I found out there is no such deleteAllVersions(key), you have to get all versionIds of your object and iterate and delete each version.
The next hurdle is, there is no such listAllVersions(key), only a listAllVersions(prefix). So if I want to listAllVersions("a") of object "a" with prefix "a" as filter, I also get all version of "aa", "ab", "ac" and so on.
It is now possible to iterate an ignore all objects not having exactly key "a". But how to handle a truncated response?
How to delete all versions of an object with a specific key, including versions marked deleted?
Use ListObjectVersionsIterable returned by listObjectVersionsPaginator:
//Pre-filter with prefix
ListObjectVersionsRequest listRequest = ListObjectVersionsRequest.builder().bucket(bucketName).prefix(key).build();
ListObjectVersionsIterable responses = s3Client.listObjectVersionsPaginator(listRequest);
for (ObjectVersion objectVersion : responses.versions())
{
//Filter pre-filtered result
if (objectVersion.key().equals(key))
{
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder().bucket(bucketName).key(key).versionId(versionId).build();
DeleteObjectResponse response = s3Client.deleteObject(deleteRequest);
}
}
The Paginator will handle the calls internally: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#listObjectVersionsPaginator-software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest-
Related
I need to serialize a map to a json in a certain order.
This is the map
HashMap<String, String> dataMap = {
"CompanyCode": "4",
"EntyyCode": "2002296",
"SubEntityCode": "000",
"ContractNumber": "52504467115",
"Progressive Contract": "0",
"DocumentNumber": "200003333494028",
"LogonUserName": "AR333",
"Progressive Title": "0"
}
This is the json model I would like:
{
"Policy": {
"ContractNumber": "52504467115",
"ProgressiveContract": "0"
},
"Title": {
"LogonUserName": "AR333",
"ProgressiveTitle": "0"
},
"BusinessChannel": {
"CompanyCode": "4",
"EntyyCode": "2002296",
"SubEntityCode": "000"
},
"Document": {
"DocumentNumber": "200003333494028"
}
}
I need to convert this map into a JSON string. I know that this can be done using Jackson as below:
new ObjectMapper().writeValueAsString(map);
How do I do this using Jackson? Or is there any other way to do this in Java?
Thank you
First of all, the solution you request contains a second problem: partition. Not only must the items contain a particular order, but they must also somehow be divided over different categories. In Java, these categories usually correspond to their own classes or, since recently, records. Then the top level class (corresponding to the unnamed outer object of the JSON) determines ordering, as so (the name Contract is my choice):
record Contract(
Policy policy,
Title title,
BusinessChannel businessChannel,
Document document )
{
}
with each of the properties of Contract having their own class, e.g.:
record Policy( String contractNumber, int progressiveContract )
etc.
Serializing Contract then recursively serializes each of its parameters, with the required outcome as the result.
This would be the 'standard' way.
So, since you start with a HashMap, which by contract offers no guarantee of ordering, let alone an easy way to partition its contents into sub-objects, you could try two things:
Rethink the use of a map. Switching to the class structure takes care of the structure automatically.
Manually stream and convert the values in order (or use e.g. a TreeMap with custom Comparator) and then partition the values themselves. This probably requires more work than a map saves.
I know it could be a duplicate, but still posting my question as i could not find the exact answer what i am looking for. I am having an json object (or string) like below.
String str = "{
"status" : {
"timestamp" : "2020-04-30T01:00:00 000Z"
"error" : 0,
"error_message" : null,
"execution" : "completed"
}
}
";
I will get the a same kind of response from my REST API testing, but after each call the 'timestamp' key will be having a dynamic date and time value with the time respect to the call made. And here i compare my expect json with the actual json as a whole sting comparison using JSONAssert. As the timestamp value is different it always fails for me.
So my question is before i do any comparison, i would like to remove the 'timestamp' key and its value from json to compare and so it will pass my case. I tried by using JsonPath also, but did not works. Any help on this please?
JSONAssert allow you to make a customized comparator while doing asserts [1].
In your case it's easy as:
JSONAssert.assertEquals(expectedJson,
actualJson,
new CustomComparator(JSONCompareMode.LENIENT,
skips("status.timestamp","another.json.path", ...)));
private static Customization[] skips(String... jsonPaths) {
return Arrays.stream(jsonPaths)
.map(jsonPath -> Customization.customization(jsonPath, (o1, o2) -> true))
.toArray(Customization[]::new);
}
Here we are defining CustomComparator, with customization which takes JSONPath (status.timestamp) and takes a ValueMatcher (lambda) which compares two values for that specific JSONPath.
In our case we will always return true, which will effectively skips the value (no matter with what we are comparing that value it's always true).
Edit: As you can see CustomComparator's constructor takes varargs of Customizations, hence you can provide more than one field to be ignore from comparison.
[1] http://jsonassert.skyscreamer.org/apidocs/org/skyscreamer/jsonassert/Customization.html
[2] http://jsonassert.skyscreamer.org/apidocs/org/skyscreamer/jsonassert/comparator/CustomComparator.html
I'm using Java GMail API and everything is working good for sending e-mails, collecting data from my profile, etc.
The only problem is that, while I can get the Signature for my 0-th element of the list of SendAs aliases, I can't get the Display Name: it returns an empty String. Both work for the other aliases (get(1) and subsequent numbers). It seems that the problem is on 0, tried on different authenticated users with Name set and it remains the same.
ListSendAsResponse aliases = service.users().settings().sendAs().list("me").execute();
SendAs mimmo = aliases.getSendAs().get(0);
actualsign = mimmo.getSignature();
sendername = mimmo.getDisplayName();
In Gmail API, there are two different ways to retrieve alias(es):
getSendAs() and SendAs.Get(java.lang.String userId,java.lang.String sendAsEmail)
The first one returns you a list of all alias, the second returns you one alias ressource - the one with the specified userId and sendAsEmail parameters.
If what you want to do it to retrieve the first element of the getSendAs() response, you should do it with getSendAs()[0] and not with the Java method get.
Sample:
SendAs mimmo = aliases.getSendAs()[0];
System.out.println(mimmo.getDisplayName());
It is always useful to test with the Try this API what response a method returns. Thereby, the userId can be set to me.
I'm using java GAE server. I store List on my entity (as strings are very limited in length in GAE). I send Map to the client through the Endpoint, and I put this list under some key. Then I retrieve this list on Android client - and I get classcast exception. It appears that HashMap< String, Object > sent from GAE server is seen as JsonMap on Client. Whatever. I proceed, I retrieve my List... and how surprised I was to find out that on the client I got List< ArrayMap >, and on this ArrayMap, my Text is under the key named "value".
There is even more. Under one of the keys in the JsonMap, I had a null value. I retrieve it... and it appears as Object (which is not null). Calling toString on this object gives me some crappy string...
Could anyone tell me why these things are happening? Sure, I can just accept how it, but its strange and not logical, and undocumented... Why my List< Text > magically converts into List< ArrayMap >? How likely is that it varies with, lets say, Android version, or, I don't know, with weather outdoor?... Anyone could help me understand these situations? Or point me some relevant documentation / articles?
Example server-side:
#ApiMethod(name = "retrievePlayer")
public Map<String, Object> retrievePlayer(Map<String, Object> data, User user) throws Exception, OAuthRequestException, IOException {
Map<String, Object> result = new HashMap<String, Object>();
List<Text> list = new ArrayList<Text>();
list.add(new Text("something"));
result.put("myList", list);
result.put("myNull", null);
return result;
}
On the client side, the "result" is of type JsonMap. The "myList" is of type ArrayList (ok). myList.get(0) is of type ArrayMap, and its one-element ArrayMap - the element inside this map has key named "value", and a value of "something". The "myNull" is of type Object and is not null, its toString() method shows something like [Ljava.lang.Object;#1db9742.
I resolved the issues by returning empty string instead of null. For the List< Text >, I iterate through it on and add all the Texts as Strings to new List< String >, and then return this new list (but it costs cpu usage on the server)... I thought it will work more predictably and out-of-the-box.
In this particular example, the method will return an instance of Map<< String, Object>>. If you try to call this endpoint using https://your_app_id.appspot.com/_ah/api/explorer, the json return will be
{ "myList" : { { "value": "something"} }, "myNull" : null }.
The returned json seems to be correct and a null is returned for "myNull". The reason you are getting an instance of Object and not null is because of the handling of JSON null by the JSON library. Please check this link for more explanation (JSON null section).
As for why the List<< Text>> magically converts into List<< ArrayMap>>, this is because you define the return as an instance of Map<< String, Object>> and the returned json does not contain any type information. I think when converting to client objects the type information is obtained from the generated client code which is based on the signature of the ApiMethod.
I've gone through the related questions on this site but haven't found a relevant solution.
When querying my Solr4 index using an HTTP request of the form
&facet=true&facet.field=country
The response contains all the different countries along with counts per country.
How can I get this information using SolrJ?
I have tried the following but it only returns total counts across all countries, not per country:
solrQuery.setFacet(true);
solrQuery.addFacetField("country");
The following does seem to work, but I do not want to have to explicitly set all the groupings beforehand:
solrQuery.addFacetQuery("country:usa");
solrQuery.addFacetQuery("country:canada");
Secondly, I'm not sure how to extract the facet data from the QueryResponse object.
So two questions:
1) Using SolrJ how can I facet on a field and return the groupings without explicitly specifying the groups?
2) Using SolrJ how can I extract the facet data from the QueryResponse object?
Thanks.
Update:
I also tried something similar to Sergey's response (below).
List<FacetField> ffList = resp.getFacetFields();
log.info("size of ffList:" + ffList.size());
for(FacetField ff : ffList){
String ffname = ff.getName();
int ffcount = ff.getValueCount();
log.info("ffname:" + ffname + "|ffcount:" + ffcount);
}
The above code shows ffList with size=1 and the loop goes through 1 iteration. In the output ffname="country" and ffcount is the total number of rows that match the original query.
There is no per-country breakdown here.
I should mention that on the same solrQuery object I am also calling addField and addFilterQuery. Not sure if this impacts faceting:
solrQuery.addField("user-name");
solrQuery.addField("user-bio");
solrQuery.addField("country");
solrQuery.addFilterQuery("user-bio:" + "(Apple OR Google OR Facebook)");
Update 2:
I think I got it, again based on what Sergey said below. I extracted the List object using FacetField.getValues().
List<FacetField> fflist = resp.getFacetFields();
for(FacetField ff : fflist){
String ffname = ff.getName();
int ffcount = ff.getValueCount();
List<Count> counts = ff.getValues();
for(Count c : counts){
String facetLabel = c.getName();
long facetCount = c.getCount();
}
}
In the above code the label variable matches each facet group and count is the corresponding count for that grouping.
Actually you need only to set facet field and facet will be activated (check SolrJ source code):
solrQuery.addFacetField("country");
Where did you look for facet information? It must be in QueryResponse.getFacetFields (getValues.getCount)
In the solr Response you should use QueryResponse.getFacetFields() to get List of FacetFields among which figure "country". so "country" is idenditfied by QueryResponse.getFacetFields().get(0)
you iterate then over it to get List of Count objects using
QueryResponse.getFacetFields().get(0).getValues().get(i)
and get value name of facet using QueryResponse.getFacetFields().get(0).getValues().get(i).getName()
and the corresponding weight using
QueryResponse.getFacetFields().get(0).getValues().get(i).getCount()