I want to access Domino data via the Domino Access Services (DAS) as REST provider in java e.g.
String url = "http://malin1/fakenames.nsf/api/data/collections/name/groups";
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(new URL(url));
JsonNode rootNode = mapper.readTree(parser);
however, I notice DAS binds the JSON in square brackets:
[
{
"#entryid":"1-D68BB54DEA77AC8085256B700078923E",
"#unid":"D68BB54DEA77AC8085256B700078923E",
"#noteid":"1182",
"#position":"1",
"#read":true,
"#siblings":3,
"#form":"Group",
"name":"LocalDomainAdmins",
"description":"This group should contain all Domino administrators in your domain. Most system databases and templates give people in this group Manager access."
},
{
"#entryid":"3-9E6EABBF405A1A9985256B020060E64E",
"#unid":"9E6EABBF405A1A9985256B020060E64E",
"#noteid":"F46",
"#position":"3",
"#read":true,
"#siblings":3,
"#form":"Group",
"name":"OtherDomainServers",
"description":"You should add all Domino servers in other domains with which you commonly replicate to this group."
}
]
How can I easily get rid of these brackets?
As already mentioned you should leave them intact. You can parse theJSON array for example with Jackson.
find an example snippet below
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
...
String response = ... your posted string
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode taskIdsjsonNode = mapper.readTree(response);
for (JsonNode next : taskIdsjsonNode) {
System.out.printf("%s: %s%n", "#entryid", next.get("#entryid"));
System.out.printf("%s: %s%n", "name", next.get("name"));
}
} catch (.... ) {
// your exception handling goes here
}
output
#entryid: "1-D68BB54DEA77AC8085256B700078923E"
name: "LocalDomainAdmins"
#entryid: "3-9E6EABBF405A1A9985256B020060E64E"
name: "OtherDomainServers"
The brackets are not nasty but a correct notation. To access the contens just use [0] in your client side script or with your JSON parser in Java you like.
Perhaps the explanation here can help:
https://quintessens.wordpress.com/2015/05/08/processing-json-data-from-domino-access-services-with-jackson/
Basically you establish a call to DAS via the Jersey client and then you parse the json via Jackson library to a map in java.
During the parsing process you can define which values you want to parse and transform them.
Take a look at the Person class...
Related
For example, we are getting a json message like this from our partner:
{
"message": "Dear client,\nWe'd like to offer you.."
}
The partner wants the client to receive the message like this (without newline but with \n)
Dear client,\nWe'd like to offer you
But we have a chain of microservices in our ecosystem and that json goes through 4 or 5 microservices which proccesing it before client can get it. So, our partner should give us \\\\\\\\n instead of \n in order to client got \n in the result. But I'm wondering, is adding 8 backslashes in the source message to escape "\n" for every microservice the only way to solve this problem. I think it's not really good solution, because we have to make changes in source message if count of microservices in chain changes (Moreover, we will face he problem if count of microservices in the chain start changing dynamically)? Is there way to use \n in source message (from partner) without replacing every \n with \\n in our microservies?
There is an example how I process the json in one of the microservices:
private String replace(String sourceJson, List<String> properties, DocumentContext context) {
StringBuilder stringBuilder = new StringBuilder(sourceJson);
for (String property : properties) {
String newValue = Pattern.compile("ABC")
.matcher(stringBuilder)
.replaceAll(context.read(property, String.class));
stringBuilder.replace(0, stringBuilder.length(), newValue);
}
return stringBuilder.toString();
}
Here's an example of creating a JSON object, turning it into a String and and then back into a JsonObject, adding a property, and turning it back into a String again.
package org.example;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class App {
public static void main(String[] args) {
JsonObject o = new JsonObject();
o.addProperty("message","foo\nbar");
Gson gson = new Gson();
String stringRep = gson.toJson(o);
System.out.println(stringRep);
JsonObject o2 = gson.fromJson(stringRep, JsonObject.class);
o2.addProperty("newProp", 42);
String messageValue = o2.get("message").getAsString();
System.out.println(messageValue);
String newMessageValue = messageValue.replace("foo", "baz");
o2.addProperty("message", newMessageValue);
stringRep = gson.toJson(o2);
System.out.println(stringRep);
}
}
The output of this program is:
{"message":"foo\nbar"}
foo
bar
{"message":"baz\nbar","newProp":42}
So you can see the the Java representations of strings contain newline characters, but the JSON representations contain the character sequence '\', 'n'.
The maven dependency you need is:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
All the answers on stackoverflow regarding Jackson I found deal with only single root node unwrapping for JSONs like
{
"user":
{
"name":"Sam Smith",
"age":1
}
}
The solution is to either use wrapper classes or use .withRootName("user") call like this
User user = objectMapper.reader()
.forType(User.class)
.withRootName("user")
.readValue(string);
also annotating User class with#JsonRootName(value = "user") is the option.
But is there an option to NOT use wrapper classes for JSONs with several parallel root nodes like this:
{
"user":
{
"name":"Sam Smith",
"age":1
},
"timestamp":
{
"clickpoint":"AE12",
"purchasable":"false"
}
}
. Can't find a solution for that. Jackson will throw an exception of not matching root name "timestamp" with expected "user". Thank you for help if you know the answer.
To operate with objects without named root you can deal with JsonNode like in the example below:
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.reader().readTree(source);
User user = mapper.treeToValue(node.get("user"), User.class);
Timestamp timestamp = mapper.treeToValue(node.get("timestamp"), Timestamp.class);
System.out.println(user.getName());
System.out.println(timestamp.getClickpoint());
In older version of Jackson instead of treeToValue() you can use readValue() with the same arguments.
I'm working with the MarkLogic POJO Databinding Interface at the moment. I'm able to write POJOs to MarkLogic. Now I want to search those POJOs and retrieve the search results. I'm following the instructions from: https://docs.marklogic.com/guide/java/binding#id_89573 However, the search results don't seem to return the correct objects. I'm getting a JSONMappingException. Here's the code:
HashMap<String, MatchedPropertyInfo> matchedProperties = new HashMap<String, MatchedPropertyInfo>();
PropertyMatches PM = new PropertyMatches(123,"uri/prefix/location2", "uri/prefix", 1234,0,"/aKey","/aLocation",true,matchedProperties);
MatchedPropertyInfo MPI1 = new MatchedPropertyInfo("matched/property/uri1", "matched/property/key1", "matched/property/location1", true,"ValueMatch1", 12, 1*1.0/3, true);
MatchedPropertyInfo MPI2 = new MatchedPropertyInfo("matched/property/uri2", "matched/property/key2", "matched/property/location2", true,"ValueMatch2", 14, 1.0/2.0, true);
PM.getMatchedProperties().put("matched/property/prefix/location1", MPI1);
PM.getMatchedProperties().put("matched/property/prefix/location2", MPI2);
PojoRepository myClassRepo = client.newPojoRepository(PropertyMatches.class, Long.class);
myClassRepo.write(PM);
PojoQueryBuilder qb = myClassRepo.getQueryBuilder();
PojoPage<PropertyMatches> matches = myClassRepo.search(qb.value("uri", "uri/prefix/location2"),1);
if (matches.hasContent()) {
while (matches.hasNext()) {
PropertyMatches aPM = matches.next();
System.out.println(" " + aPM.getURI());
}
} else {
System.out.println(" No matches");
}
The PropertyMatches (PM) object is succesfully written to the MarkLogic database. This class contains a member: private String URI which is initiated with "uri/prefix/location2". The matches.hasContent() returns true in the example above. However, I'm getting an error on PropertyMatches aPM = matches.next();
Searching POJOs in MarkLogic and read them into your Java program requires the POJOs to have an empty constructor. In this case PropertyMatches should have public PropertyMatches(){} and MatchedPropertyInfo should have public MatchedPropertyInfo(){}
Thanks #sjoerd999 for posting the answer you found. Just to add some documentation references, this topic is discussed here: http://docs.marklogic.com/guide/java/binding#id_54408 and here: https://docs.marklogic.com/javadoc/client/com/marklogic/client/pojo/PojoRepository.html.
Also worth noting is you can have multiple parameters in the consructor, you just have to do it the Jackson way. Here are examples of two ways (with annotations and without): https://manosnikolaidis.wordpress.com/2015/08/25/jackson-without-annotations/
I'd recommend using annotations as that's built-in with Jackson. But if you want to do it without annotations, here's the code:
ObjectMapper mapper = new ObjectMapper();
// Avoid having to annotate the Person class
// Requires Java 8, pass -parameters to javac
// and jackson-module-parameter-names as a dependency
mapper.registerModule(new ParameterNamesModule());
// make private fields of Person visible to Jackson
mapper.setVisibility(FIELD, ANY);
If you want to do this with PojoRepository you'll have to use the unsupported getObjectMapper method to get the ObjectMapper and call registerModule and setVisibility on that:
ObjectMapper objectMapper = ((PojoRepositoryImpl) myClassRepo).getObjectMapper();
I am trying to deserialize the following incoming JSON data:
{"TimeTable":[{"PersonID":"100649771",
..,..,..,"xx":null},
{"PersonID":"100631701",
..,..,..,"xx":{"abc":1234,"xyz":5678}}],
"xxx":"","xxxx":0,"xxxxx":false}
But I am facing a problem while parsing using a custom deserialization block made up of:
jParser.nextToken();
while ((jParser.nextToken() != JsonToken.END_ARRAY)) {
String innerField = jParser.getCurrentName();
jParser.nextToken();
But in this way I am skipping the array contents While parsing for the second row in the array (as illustrated in the JSON sample above^).
UPDATE: Here is the method(PasteBin Link) which is trying to parse the JSON data coming in the described format. Is there a way I can bind the JSON data directly to my bean? (IMO it appeared way more complex to me as because of the JSON structure; Moreover I can't change the JSON structure nor the bean structure. So, I just dropped the idea of binding directly :| ) Anyways here(PasteBin Link) is the bean as well.
Following is the sample of the incoming JSON Data:
{"Schedules":[{"PersonID":"100649771",
"HasSchedule":false,
"TripType":null,
"StickerNumber":null,
"VehicleRegNo":null,
"ExpectedStartDate":null,
"ActualStartDate":null,
"ActualEndDate":null,
"PersonScheduledDate":null,
"Shift":null,
"ColdCall":null,
"PickupLocationCoord":null},
{"PersonID":"100631701",
"HasSchedule":true,
"TripType":"P",
"StickerNumber":"PC0409",
"VehicleRegNo":"ASJHAHSP1758",
"ExpectedStartDate":"16 Aug 2013, 10:00:00",
"ActualStartDate":"16 Aug 2013, 10:02:52",
"ActualEndDate":"16 Aug 2013, 14:14:12",
"PersonScheduledDate":null,
"Shift":"02:30 PM",
"ColdCall":"N",
"PickupLocationCoord":{"Latitude":92.01011101,"Longitude":48.01011101}}],
"ErrorMessage":"","ErrorCode":0,"HasError":false}
Please can anyone fireup some pointers for me here in order- to deserialize 'em correctly?
Thanks
UPDATED
Among other things, you are mixing up the two aproaches to read a JSON stream: using readTree() to get all your JSON data in a memory tree (like XML's DOM) but also using a JsonParser to read a JSON stream token by token (like XML's JAX). The following is a method that does almost the same using readTree(), which seems to be more appropriate to you as you are reading JSON already loaded in a String:
public List<VehicleInformationBean> getAllVehiclesInTree(String response) {
List<VehicleInformationBean> vehicleList = new ArrayList<VehicleInformationBean>();
try {
PersonInformationBean mPersonInformationBean;
DatabaseHelper mDatabaseHelper = DatabaseHelper.getInstance(sContext);
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = (ObjectNode) mapper.readTree(response);
if ((root.get(ServiceConstant.ErrorCode).asInt()) != 0 || !root.has(ServiceConstant.Schedules)) {
return vehicleList;
}
for(JsonNode element: root.get(ServiceConstant.Schedules)) {
VehicleInformationBean lstVehicleInformation = new VehicleInformationBean();
if (element.has(ServiceConstant.PersonID)) {
String personId = element.get(ServiceConstant.PersonID).asText();
mPersonInformationBean = mDatabaseHelper.getPersonDetailById(personId);
lstVehicleInformation.setPersonID(personId);
lstVehicleInformation.setName(mPersonInformationBean.getName());
lstVehicleInformation.setPickupLocation(mPersonInformationBean.getPickupLocation());
lstVehicleInformation.setDropLocation(mPersonInformationBean.getDropLocation());
}
lstVehicleInformation.setTripType(element.get(ServiceConstant.TripType).textValue());
lstVehicleInformation.setStickerNumber(element.get(ServiceConstant.StickerNumber).textValue());
lstVehicleInformation.setVehicleRegNo(element.get(ServiceConstant.VehicleRegNo).textValue());
lstVehicleInformation.setExpectedStartDate(element.get(ServiceConstant.ExpectedStartDate).textValue());
lstVehicleInformation.setActualStartDate(element.get(ServiceConstant.ActualStartDate).textValue());
lstVehicleInformation.setActualEndDate(element.get(ServiceConstant.ActualEndDate).textValue());
lstVehicleInformation.setPersonScheduledDate(element.get(ServiceConstant.PersonScheduledDate).textValue());
lstVehicleInformation.setShift(element.get(ServiceConstant.Shift).textValue());
if (element.has("PickupLocationCoord")) {
JsonNode coords = element.get("PickupLocationCoord");
if(coords.has(ServiceConstant.Latitude)) {
lstVehicleInformation.setLatitude(coords.get(ServiceConstant.Latitude).asDouble());
}
if(coords.has(ServiceConstant.Longitude)) {
lstVehicleInformation.setLongitude(coords.get(ServiceConstant.Longitude).asDouble());
}
} else if (element.has(ServiceConstant.ColdCall)) {
lstVehicleInformation.setColdCall(element.get(ServiceConstant.ColdCall).textValue());
}
vehicleList.add(lstVehicleInformation);
}
} catch (Exception e) {
// TODO doing something with exception or throw it if it can't be handled here
e.printStackTrace();
}
return vehicleList;
}
There are some validations and extra code you need to add to this method for it to do exactly what your original method does. This method only shows you the main idea of how to do it.
I am searching through solr. it gives me response in json. like following:
{response
{numfound:# , docs{
[
{
id="#"
model="#"
}
{
id="#"
model="#"
}
]
}
}
I want to extract just the ids from this and make java array list from them.
Can someone please tell me how i can do that in coding language?
question: how to just extract id from son string and convert then into java array list if i am using hashmap or objectmapper in java?
thanx
If you want to convert into java objects, you can work with Solr Client Solrj
Solrj will give you and easy option to query Solr and read the xml to convert into java objects
For JSON you can use jackson library for parsing Solr response.
Here is a small program that will read the data using the Gson library.
#Test
public void testRead() throws IOException {
final String testUrl = "http://localhost:8983/solr/collection1/select?q=*%3A*&wt=json&indent=true";
String out = new Scanner(new URL(testUrl).openStream(), "UTF-8").useDelimiter("\\A").next();
SolrResult result = new Gson().fromJson(out, SolrResult.class);
List<String> ids = new ArrayList<String>();
for (Doc doc : result.response.docs) {
ids.add(doc.id);
}
System.err.println(ids);
}
It uses the following three small classes as a Java representation of the response:
public class SolrResult {
public Response response;
}
class Response {
public int numFound;
public int start;
public List<Doc> docs;
}
class Doc {
public String id;
}
I hope this helps.
As Jayendra pointed you can use SolrJ if you are querying Solr using Java. I don't suggest to use XML as response format due to XML parsing overhead. SolrJ supports java binary object encoding (using commons-codec) out-of-the-box and by default on queries.
To use it on updates you have to set it up manually using
server.setRequestWriter(new BinaryRequestWriter());
and you have to enable the BinaryUpdateHandler on the server too, using:
<requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler" />
In the case you don't want to use SolrJ you can parse it using GSON. Here you have and example.