I am using MongoDB Driver Java API to convert BSON to JSON.
I have test code like this.
String input = "{ \"timestamp\" : 1486064586641 }";
org.bson.Document doc = org.bson.Document.parse(input);
System.out.println("input = " + input);
System.out.println("output = " + doc.toJson());
The output is:
input = { "timestamp" : 1486064586641 }
output = { "timestamp" : { "$numberLong" : "1486064586641" } }
Is there an easy way to make the output look like the input?
BSON Documnet's toJson method supports only output to MongoDB Extended JSON (STRICT or SHELL format). If you want to have regular JSON, you can use com.mongodb.util.JSON class:
String input = "{ \"timestamp\" : 1486064586641 }";
org.bson.Document doc = org.bson.Document.parse(input);
System.out.println("input = " + input);
System.out.println("output (SHELL) = " + doc.toJson(new JsonWriterSettings(JsonMode.SHELL)));
System.out.println("output (STRICT) = " + doc.toJson(new JsonWriterSettings(JsonMode.STRICT)));
System.out.println("output (JSON) = " + com.mongodb.util.JSON.serialize(doc));
This will generate following output:
input = { "timestamp" : 1486064586641 }
output (SHELL) = { "timestamp" : NumberLong("1486064586641") }
output (STRICT) = { "timestamp" : { "$numberLong" : "1486064586641" } }
output (JSON) = { "timestamp" : 1486064586641}
Natalja's answer is excellent, but if you are using the Mongo Java driver 3.8.2 upwards you will notice some deprecation warnings. If you want the output to look like the input you can use RELAXED JsonWriterSettings mode.
Below you can see an example with the possible modes and how the JSON will looks like. There are also some deprecation warnings and alternatives to the deprecated code:
String input = "{ \"timestamp\" : 1486064586641 }";
org.bson.Document doc = org.bson.Document.parse(input);
System.out.println("input = " + input);
JsonWriterSettings shellMode = JsonWriterSettings.builder().outputMode(JsonMode.SHELL).build();
System.out.println("output (SHELL) = " + doc.toJson(shellMode));
JsonWriterSettings strictMode = JsonWriterSettings.builder().outputMode(JsonMode.STRICT).build();
System.out.println("output (STRICT) = " + doc.toJson(strictMode)); // deprecated - use extended like below
JsonWriterSettings extendedMode = JsonWriterSettings.builder().outputMode(JsonMode.EXTENDED).build();
System.out.println("output (EXTENDED) = " + doc.toJson(extendedMode));
JsonWriterSettings relaxed = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build();
System.out.println("output (RELAXED) = " + doc.toJson(relaxed));
System.out.println("output (JSON) = " + com.mongodb.util.JSON.serialize(doc)); // deprecated - use relaxed like above
Also note that the JsonWriterSettings constructor is deprecated and you can use as an alternative the builder method like e.g:
JsonWriterSettings.builder().outputMode(JsonMode.SHELL).build()
Related
I have a JSON file as below and want to convert to json with Name key , value pair ,
Eg : "name":"emailAddress",
"value" :"Trest22#gmail.com"
If have multiple JSON tags then it should break into separate tag as shown in image.
Please help
[
{
"emailAddress": "Trest22#gmail.com",
"loginName": "Testinguser222",
"firstName": "Test222",
"surName": "Test22",
"primaryPhone": "",
"companyId": 123445,
"extracompanies": "[12311,33333]",
"middleName": "Test",
"mobilePhone": 6666666666,
"fax": 87687687686
}
]
Want to convert as below
{
{
"name":"emailAddress",
"value" :"Trest22#gmail.com"
}
{
"name":"loginName",
"value":"Testinguser222"
}
{
"name":"firstName",
"value":"Test222"
}
{
"name":"surName",
"value":"Test22"
}
{ "name":"extracompanies",
"value": "[12311,33333]"
}
I am not sure if any library can do that, however, in Java, you can achieve it as shown below,
ObjectMapper mapper = new ObjectMapper();
String test = "{\n" +
" \"emailAddress\": \"Trest22#gmail.com\",\n" +
" \"loginName\": \"Testinguser222\",\n" +
" \"firstName\": \"Test222\",\n" +
" \"surName\": \"Test22\",\n" +
" \"primaryPhone\": \"\",\n" +
" \"companyId\": 123445,\n" +
" \"extracompanies\": \"[12311,33333]\",\n" +
" \"middleName\": \"Test\",\n" +
" \"mobilePhone\": 6666666666,\n" +
" \"fax\": 87687687686\n" +
" \n" +
" }";
Map<String, Object> maps = mapper.readValue(test, Map.class);
List<Map<String,Object>> converted = maps.keySet().stream().map(key -> {
Map<String,Object> internalMap = new HashMap<>();
internalMap.put("name", key);
internalMap.put("value", maps.get(key));
return internalMap;
}).collect(Collectors.toList());
String json = mapper.writeValueAsString(converted);
Output
[{"name":"emailAddress","value":"Trest22#gmail.com"},{"name":"loginName","value":"Testinguser222"},{"name":"firstName","value":"Test222"},{"name":"surName","value":"Test22"},{"name":"primaryPhone","value":""},{"name":"companyId","value":123445},{"name":"extracompanies","value":"[12311,33333]"},{"name":"middleName","value":"Test"},{"name":"mobilePhone","value":6666666666},{"name":"fax","value":87687687686}]
I am using java to extract a list of node ids from an elastic search running tasks response.
The response looks like this
{
"nodes": {
"ZKUuxQZpRCCcJ0njBM1P0A": {
"name": "ZKUuxQZ",
"transport_address": "127.0.0.1:9300",
"host": "127.0.0.1",
"ip": "127.0.0.1:9300",
"roles": [
"master",
"data",
"ingest"
],
"tasks": {
"ZKUuxQZpRCCcJ0njBM1P0A:118": {
"node": "ZKUuxQZpRCCcJ0njBM1P0A",
"id": 118,
"type": "transport",
"action": "indices:data/write/delete/byquery",
"start_time_in_millis": 1527808643421,
"running_time_in_nanos": 154234724059,
"cancellable": true,
"headers": {}
}
}
}
}
}
In this example, I want to exact ZKUuxQZpRCCcJ0njBM1P0A:118. Can someone give me an example how to extract this information?
Option 1, java json parser. I wanted to write a response class and parse the json string, but ZKUuxQZpRCCcJ0njBM1P0A:118 is not in the key:value format. I am not sure how to extract it.
Option 2, using regex. The node id part may also have - or _. Can someone provide a neat java regex solution? So far my regex is [a-zA-Z0-9\-\_]+\:[0-9]+, I am not sure if this is safe enough.
Thanks.
One way you can do this is by using org.json library and create JSONObject and using keys() you can get all the keys and use this to achieve your task
Add the following dependency in your pom.xml
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
Then you can do something like below:
String jsonString = "{\n" +
" \"nodes\": {\n" +
" \"ZKUuxQZpRCCcJ0njBM1P0A\": {\n" +
" \"name\": \"ZKUuxQZ\",\n" +
" \"transport_address\": \"127.0.0.1:9300\",\n" +
" \"host\": \"127.0.0.1\",\n" +
" \"ip\": \"127.0.0.1:9300\",\n" +
" \"roles\": [\n" +
" \"master\",\n" +
" \"data\",\n" +
" \"ingest\"\n" +
" ],\n" +
" \"tasks\": {\n" +
" \"ZKUuxQZpRCCcJ0njBM1P0A:118\": {\n" +
" \"node\": \"ZKUuxQZpRCCcJ0njBM1P0A\",\n" +
" \"id\": 118,\n" +
" \"type\": \"transport\",\n" +
" \"action\": \"indices:data/write/delete/byquery\",\n" +
" \"start_time_in_millis\": 1527808643421,\n" +
" \"running_time_in_nanos\": 154234724059,\n" +
" \"cancellable\": true,\n" +
" \"headers\": {}\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
JSONObject jsonObject = new JSONObject(jsonString);
Set<String> topLevelKeys = jsonObject.keySet();
for (String key : topLevelKeys) {
Object value = jsonObject.get(key);
if (value instanceof JSONObject) {
JSONObject valueObject = jsonObject.getJSONObject(key);
System.out.println(valueObject.toString());
}
}
Extend this as per your requirement.
So regex is too hacky and I figured it out using gson. I wish ElasticSearch can offer us some standard library to extract all kinds of responses. Here is my solution using gson.
import com.google.gson.*;
import org.json.JSONObject;
public class test {
public static void main(String[] args) throws Exception {
String jsonString = "json_format elasticsearch reponse for listing running tasks"
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(content).getAsJsonObject();
jsonObject.getAsJsonObject("nodes").entrySet().forEach(
s -> {
s.getValue().getAsJsonObject().getAsJsonObject("tasks").entrySet().forEach( s2 -> {
System.out.println(s2.getKey());
});
});
}
It prints all the running task ids like the following. It's technically nodeId:taskId, but ES has a very vague description in their task API docs(It says you can use TASK_ID to check a status of a task, well that TASK_ID is nodeId:taskId).
Mw-3i39gTHGxu5c8z9viQQ:503209021
DZ29LMsWR0aW9guWZTYe2Q:482931604
6CAbDZSWR8SfwZgnRT0qNg:494351185
Use the following regex:
[a-zA-Z0-9-_]*[0-9]+[a-zA-Z]+:[0-9]*
You can find the test result here:
https://regexr.com/3qdug
I parsed a Json string with JObject.Parse(json) and I'm trying to traverse the properties. I find that the only way to access the json type is thru it's parent node, like this:
string json = #"{
CPU: 'Intel',
Drives: [ 'DVD read/writer', '500 gigabyte hard drive'
]
}";
JObject o = JObject.Parse(json);
foreach (var p in o.Properties())
{
Console.WriteLine("name:" + p.Name + ", value: " + p.Value);
Console.WriteLine("o[p.Name].Type: " + o[p.Name].Type); // correctly returns js type
Console.WriteLine("p.Type: " + p.Type); // returns Property for every item
Console.WriteLine("p.GetType(): " + p.GetType()); // returns Newtonsoft.Json.Linq.JProperty for every item
Console.WriteLine();
}
I suppose there must be some way to get the json type from the property. (live fiddle here)
The Value of a JProperty is a JToken. You can use the Type property on a JToken to get its JSON type. So you just need to use p.Value.Type to get what you are looking for.
Example fiddle: https://dotnetfiddle.net/CtuGGz
using System;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = #"
{
""CPU"": ""Intel"",
""Integrated Graphics"": true,
""USB Ports"": 6,
""OS Version"": 7.1,
""Drives"": [
""DVD read/writer"",
""500 gigabyte hard drive""
]
}";
JObject o = JObject.Parse(json);
foreach (var p in o.Properties())
{
Console.WriteLine("name: " + p.Name);
Console.WriteLine("type: " + p.Value.Type);
Console.WriteLine("value: " + p.Value);
Console.WriteLine();
}
}
}
I need to create a view with a map function ex:
function(doc, meta) {
if(doc.docType == "testDoc")
emit(meta.id, doc)
}
I have to create this view using couchbase java client 2.1.I could not find any thing in the documentation thanks
Here is some code to create a design document:
List<View> viewsForCurrentDesignDocument = new ArrayList<View>();
DesignDocument designDocument = DesignDocument.create("my_design_doc", viewsForCurrentDesignDocument);
And add a view:
String mapFunction =
"function (doc, meta) {\n" +
" if(doc.docType == \"testDoc\") {\n" +
" emit(meta.id, doc);\n" +
" }\n" +
"}";
String reduceFunction = "..." // or null if no reduce
View v = DefaultView.create("my_view", mapFunction, reduceFunction);
viewsForCurrentDesignDocument.add(v);
bucket.bucketManager().insertDesignDocument(designDocument);
You can check the API reference for more options(development mode, timeout, ...).
Consider the following json example
{
"key1" : {
"k11":["vala","valb","valc"],
"k12":["vald"],
"k13":["vale","valf"]
},
"key2" : {
"key21":["valg","valh","vali"],
"key22":["valj"],
"key23":["valk","vall"]
}
}
This translates into a Map<String,Map<String,List<String>>>.
Could anyone please let me know how i can convert this in this into this complex Map object. I do a a method called constructMapType, but not sure if it handles complex Map type.
Seems to work fine with .constructMapType(Map.class, String.class, Map.class)
public static void main(String[] args) throws Exception {
final String json
= "{\n"
+ " \"key1\" : {\n"
+ " \"k11\":[\"vala\",\"valb\",\"valc\"],\n"
+ " \"k12\":[\"vald\"],\n"
+ " \"k13\":[\"vale\",\"valf\"]\n"
+ " },\n"
+ " \"key2\" : {\n"
+ " \"key21\":[\"valg\",\"valh\",\"vali\"],\n"
+ " \"key22\":[\"valj\"],\n"
+ " \"key23\":[\"valk\",\"vall\"]\n"
+ " }\n"
+ "}";
ObjectMapper mapper = new ObjectMapper();
Map<String, Map<String, List<String>>> map
= mapper.readValue(json,TypeFactory.defaultInstance()
.constructMapType(Map.class, String.class, Map.class));
for (String outerKey: map.keySet()) {
System.out.println(outerKey + ": " + map.get(outerKey));
for (String innerKey: map.get(outerKey).keySet()) {
System.out.print(innerKey + ": [");
for (String listValue: map.get(outerKey).get(innerKey)) {
System.out.print(listValue + ",");
}
System.out.println("]");
}
}
}
You could go all the way down listing all the generics down to the List<String>, but as seen above it isn't necessary. But just to show what I mean
TypeFactory factory = TypeFactory.defaultInstance();
Map<String, Map<String, List<String>>> map
= mapper.readValue(json, factory.constructMapType(
Map.class,
factory.constructType(String.class),
factory.constructMapType(
Map.class,
factory.constructType(String.class),
factory.constructCollectionType(
List.class,
String.class))));