I'm trying to update an object in couchbase server 5.1.1 .
additionalCodes is a list of object
Code(String code,String type,LocalDateTime datetime )
my object in couchbase is like this :
{
"code": "code1";
"creationDateTime": 1534852560000,
"additionalCodes": [
{
"code": "code1",
"type": "type1",
"dateTime": 1534772384000
}
]
}
and i do want to update this object like :
{
"code": "code1";
"creationDateTime": 1534852560000,
"additionalCodes": [
{
"code": "code1",
"type": "type1",
"dateTime": 1534772384000
},
{
"code": "code2",
"type": "type2",
"dateTime": 1534772384000
}
]
}
i'm trying this :
JsonDocument doc = bucket.get("ID");
doc.content().put("additionalCodes",new Code(...));
doc = bucket.upsert(doc);
thanks in advance
There's a few ways of doing this. You can manually convert your object graph into corresponding Json* classes:
// Code code = new Code(...);
JsonDocument doc = bucket.get("ID");
JsonArray curAddlCodes = doc.content().getArray("additionalCodes");
JsonObject newCode = JsonObject.create()
.put("code", code.code)
.put("type", code.type)
.put("dateTime", code.dateTime.toEpochSecond());
curAddlCodes.add(newCode);
doc = bucket.replace(doc);
Or you can use the subdoc API to efficiently update just the additionalCodes field, without having to fetch and send the full document:
bucket.mutateIn("ID")
.arrayAppend("additionalCodes", newCode)
.execute();
If you have a full object graph such as:
TopLevelCode(String code, LocalDateTime creationDateTime, List<Code> additionalCodes)
then you have a couple more options. You can manipulate the POJOs are you wish, then serialize it to a JSON string using a library like Jackson, and store it in a RawJsonDocument:
// TopLevelCode tlc = new TopLevelCode(...)
ObjectMapper objectMapper = com.couchbase.client.java.transcoder.JacksonTransformers.MAPPER;
String json = objectMapper.writeValueAsString(tlc);
RawJsonDocument doc = RawJsonDocument.create("ID", json);
bucket.replace(doc);
Or, if your object graph is Serializable, you could use SerializableDocument:
SerializableDocument doc = SerializableDocument.create("ID", tlc);
bucket.replace(doc);
Related
I have a string like below
{
"id": "abc",
"title": "123.png",
"description": "fruits",
"information": [
{
"type": "apple",
"url": "https://apple.com"
},
{
"type": "orange",
"url": "https://orange.com"
}
],
"versions": 0
}
I want to get the value of url where type: orange. The list in information may not always be in same order as appearing in the data above. I know I could do it easily in python with json.loads and json.dump.
I am trying to do it java using JsonNode and objectMapper.readTree.at("/information") but I am unable to get past this point in a clever neat way to get the list and fetch the url where type = orange.
This is pretty straightforward
Use a JSON library and parse the response using the library. Then get only the values and attributes that you need...
Example relevant to your case:
// Get your Json and transform it into a JSONObject
JSONObject mainObject = new JSONObject(yourJsonString); // Here is your JSON...
// Get your "information" array
JSONArray infoArray = mainObject.getJSONArray("information"); // Here you have the array
// Now you can go through each item of the array till you find the one you need
for(int i = 0 ; i < infoArray.length(); i++)
{
JSONObject item = participantsArray.getJSONObject(i);
final String type = item.getString("type");
final String url = item.getString("url");
if(type.equals("orange"))
{
// DO WHATEVER YOU NEED
}
}
I am currently working on elastic search through my java Application . I know how to index the Java pojo using RestHighLevelClient. How i can make search only on new fields not the complete pojo.?
public class Employee{
private long id;
private String name;
private String designation;
private String address; //want to index but not searchable in elastic search
}
My Code for indexing is below which is working fine:
public String saveToEs(Employee employee) throws IOException {
Map<String, Object> map = objectMapper.convertValue(employee, Map.class);
IndexRequest indexRequest =
new IndexRequest(INDEX, TYPE, employee.getId().toString()).source(map, XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
I need to do this in java .Any help please or good link ?
Writing another answer for RestHighLevelClient As another answer is useful for people not using the Rest client and adding this in the first answer makes it too long.
Note: you are passing the type which is deprecated in ES 7.X and I am using the ES 7.X version, so my code is according to 7.X.
CreateIndexRequest request = new CreateIndexRequest("employee");
Map<String, Object> name = new HashMap<>();
name.put("type", "text");
Map<String, Object> address = new HashMap<>();
address.put("type", "text");
address.put("index", false);
Map<String, Object> properties = new HashMap<>();
properties.put("name", name);
properties.put("address", address);
Map<String, Object> mapping = new HashMap<>();
mapping.put("properties", properties);
request.mapping(mapping);
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
Important points
I've used only 2 fields for illustration purpose, one of which is address field which is not searchable, and to do that I used, address.put("index", false); , while name is searchable field and there this option isn't present.
I've created index mapping using the Map method which is available in this official ES doc.
you can check the mapping created by this code, using mapping REST API.
Below is the mapping generated for this code in my system and you can see, index: false is added in the address field.
{
"employee": {
"mappings": {
"properties": {
"address": {
"type": "text",
"index": false
},
"name": {
"type": "text"
}
}
}
}
}
You can just use the same search JSON mentioned in the previous answer, to test that it's not searchable.
Use the index option as false on the address field, which is by default true to make it unsearchable. As mention in the same official ES link:
The index option controls whether field values are indexed. It accepts
true or false and defaults to true. Fields that are not indexed are
not queryable.
Let me show you how can you test it using the REST API and then the java code(using rest-high level client) to accomplish it.
Mapping
{
"mappings": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text"
},
"designation": {
"type": "text"
},
"address": {
"type": "text",
"index" : false --> made `index` to false
}
}
}
}
Index few docs
{
"address" : "USA",
"name" : "Noshaf",
"id" : 234567892,
"designation" : "software engineer"
}
{
"address" : "USA california state",
"name" : "opster",
"id" : 234567890,
"designation" : "software engineer"
}
A simple match search query in JSON format on address field
{
"query": {
"match" : {
"address" : "USA"
}
}
}
Exception from Elasticsearch clearly mention, it's not searchable
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Cannot search on field [address] since it is not indexed."
}
I need to modify a particular value of a key in my json file, it is a nested JSON file and i have traversed till that key value pair but i'm not able to modify the value and don't know how to write back to the json.
Using json-simple to parse the JSON
This is the JSON file:
{
"entity": {
"id": "ppr20193060018",
"data": {
"relationships": {
"productpresentationtolot": [
{
"id": "",
"relTo": {
"id": "",
"data": {
"attributes": {
"rmsitemid": {
"values": [
{
"source": "internal",
"locale": "en-US",
"value": "2019306"
}
]
}
}
},
"type": "lot"
}
}
]
}
},
"type": "productpresentation"
}
}
Reading it using below code:
JSONParser parser = new JSONParser();
reader = new FileReader("path.json");
JSONArray rmsArray =(JSONArray) rmsitemid.get("values");
for(Object obj2:rmsArray)
{
JSONObject tempObj1=(JSONObject)obj2;
System.out.println(tempObj1.get("value"));
}
I'm able to print what is there in value(Key) i.e., 2019306 but i don't have any idea how can i replace it with some other value and it should change the value in JSON file also.
Any help appreciated!
Here is a complete exmaple how to read and write using the simple-json library:
// read from resource file
JSONObject value;
try (Reader in = new InputStreamReader(getClass().getResourceAsStream("/simple.json"))) {
JSONParser parser = new JSONParser();
value = (JSONObject) parser.parse(in);
}
JSONObject entity = (JSONObject) value.get("entity");
// update id
entity.put("id", "manipulated");
// write to output file
try (Writer out = new FileWriter("output.json")) {
out.write(value.toJSONString());
}
The JSONObjects are basically Maps. So you can just put values inside.
In order to create a JSON string again, use toJSONString().
In my example, I create a new output file. You could also override the original input file, though. But you have to write the file completely.
I am new To JSon and i want to search the following json string and get the required output.
String:
{"status":"Success","code":"200","message":"Retrieved Successfully","reason":null,"
"projects":
[
{
"projectName": "example",
"users":
[
{
"userName": "xyz",
"executions":
[
{
"status": "check",
"runs":
[
{
"Id": "------",
"Key": "---"
}
],
"RCount": 1
}
],
"RCount": 1
}
],
"RCount": 1
},
Like that i have many projects and now , if i give projectname and username as input i wantt to get its status as output.
Is it possible?If yes how?
You may use JSONObject for this.
JSONObject json = new JSONObject(string);
JSONArray[] projectsArray = json.getJSONArray("projects");
for(int i = 0; i < projectsArray.length; ++i)
{
String projectName = projectsArray[i].getString("projectName");
...
}
Use the same method to get the users.
You can use gson library. Using gson convert your json string to Map and then you can iterate through map to get required item
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> myMap = gson.fromJson(jsonString, type);
You can use the Google gson to map your json data structure to a Java POJOs.
Example :
You can have Projects class containing list/array of Users.
Users class containing list/array of Executions and so on.
Gson library can easily map the json to these classes as objects and you can access your data in a more elegant manner.
Here are a few references :
http://howtodoinjava.com/2014/06/17/google-gson-tutorial-convert-java-object-to-from-json/
http://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
I'm a new Java programmer coming from a background in Python. I have weather data that's being collected/returned as a JSON with nested keys in it, and I don't understand how pull the values out in this situation. I'm sure this question has been asked before, but I swear I've Googled a great deal and I can't seem to find an answer. Right now I'm using json-simple, but I tried switching to Jackson and still couldn't figure out how to do this. Since Jackson/Gson seem to be the most used libraries, I'd would love to see an example using one of those libraries. Below is a sample of the data, followed by the code I've written so far.
{
"response": {
"features": {
"history": 1
}
},
"history": {
"date": {
"pretty": "April 13, 2010",
"year": "2010",
"mon": "04",
"mday": "13",
"hour": "12",
"min": "00",
"tzname": "America/Los_Angeles"
},
...
}
}
Main function
public class Tester {
public static void main(String args[]) throws MalformedURLException, IOException, ParseException {
WundergroundAPI wu = new WundergroundAPI("*******60fedd095");
JSONObject json = wu.historical("San_Francisco", "CA", "20100413");
System.out.println(json.toString());
System.out.println();
//This only returns 1 level. Further .get() calls throw an exception
System.out.println(json.get("history"));
}
}
The function 'historical' calls another function that returns a JSONObject
public static JSONObject readJsonFromUrl(URL url) throws MalformedURLException, IOException, ParseException {
InputStream inputStream = url.openStream();
try {
JSONParser parser = new JSONParser();
BufferedReader buffReader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String jsonText = readAll(buffReader);
JSONObject json = (JSONObject) parser.parse(jsonText);
return json;
} finally {
inputStream.close();
}
}
With Jackson's tree model (JsonNode), you have both "literal" accessor methods ('get'), which returns null for missing value, and "safe" accessors ('path'), which allow you to traverse "missing" nodes. So, for example:
JsonNode root = mapper.readTree(inputSource);
int h = root.path("response").path("history").getValueAsInt();
which would return the value at given path, or, if path is missing, 0 (default value)
But more conveniently, you can just use JSON pointer expression:
int h = root.at("/response/history").getValueAsInt();
There are other ways too, and often it is more convenient to actually model your structure as Plain Old Java Object (POJO).
Your content could fit something like:
public class Wrapper {
public Response response;
}
public class Response {
public Map<String,Integer> features; // or maybe Map<String,Object>
public List<HistoryItem> history;
}
public class HistoryItem {
public MyDate date; // or just Map<String,String>
// ... and so forth
}
and if so, you would traverse resulting objects just like any Java objects.
Use Jsonpath
Integer h = JsonPath.parse(json).read("$.response.repository.history", Integer.class);
Check out Jackson's ObjectMapper. You can create a class to model your JSON then use ObjectMapper's readValue method to 'deserialize' your JSON String into an instance of your model class. And vice-versa.
Try jpath API. It's xpath equivalent for JSON Data. You can read data by providing the jpath which will traverse the JSON data and return the requested value.
This Java class is the implementation as well as it has example codes on how to call the APIs.
https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java
Readme -
https://github.com/satyapaul/jpath/blob/master/README.md
Example:
JSON Data:
{
"data": [{
"id": "13652355666_10154605514815667",
"uid": "442637379090660",
"userName": "fanffair",
"userFullName": "fanffair",
"userAction": "recommends",
"pageid": "usatoday",
"fanPageName": "USA TODAY",
"description": "A missing Indonesian man was found inside a massive python on the island of Sulawesi, according to local authorities and news reports. ",
"catid": "NewsAndMedia",
"type": "link",
"name": "Indonesian man swallowed whole by python",
"picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"full_picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"message": "Akbar Salubiro was reported missing after he failed to return from harvesting palm oil.",
"link": "http:\/\/www.usatoday.com\/story\/news\/nation-now\/2017\/03\/29\/missing-indonesian-man-swallowed-whole-reticulated-python\/99771300\/",
"source": "",
"likes": {
"summary": {
"total_count": "500"
}
},
"comments": {
"summary": {
"total_count": "61"
}
},
"shares": {
"count": "4"
}
}]
}
Code snippet:
String jPath = "/data[Array][1]/likes[Object]/summary[Object]/total_count[String]";
String value = JSONDataReader.getStringValue(jPath, jsonData);