Hi I need to convert Mongo Document to DBObject (BasicDBObject).
I am uploading a file to mongo using GridFS and I want to set metadata, which I get in document. I know Document is pretty much the same as DBObject. I know I can do something like this:
Document doc = new Document();
BasicDBObject.parse(doc.toJson());
But isn't this needlessly performance heavy?
The gridFS method setMetaData() accepts only DBObject so i have to convert it.
Is there a better way of doing that rather then converting it to string and back ?
You are kind of micro-optimizing here.
However, since both classes are implementations of Map, you can just do:
Document document = new Document();
BasicDBObject basicDBObject = new BasicDBObject(document);
Internally this does a Map#putAll operation that puts all entries of the Document map into the BasicDbObject map.
I know this is an old question and there is an accepted answer however it is not correct.
The proposed answer only does a shallow conversion between Document and DBOject. If your Json object contains nested objects or lists they will not be converted properly.
I got around this problem by serialising to JSON string. It is not efficient at all but might be enough in most cases, and at least it is correct:
public final class BsonConverter {
public static Document toDocument(DBObject dbObject) {
return Document.parse(dbObject.toString());
}
public static DBObject toDBObject(Document document) {
return BasicDBObject.parse(document.toJson());
}
}
Related
I've put a HashMap<String, Set<Long>> object into a MongoDB document under "disabled_channels" but I can't figure out how to retrieve it and turn it back into a HashMap<String, Set<Long>> object in local memory. I'm usually very good at reading in lists, individual values, etc, with something like found.getList("disabled_commands", String.class) but I'm really lost on how to approach this.
MongoCollection<Document> collection = bot.getDataManager().getConfig();
Document config = new Document("guild", guild.getIdLong());
Document found = collection.find(config).first();
// I get lost here
Document itself is a map implementation internally. Reference
You need to use get function on found document and cast it to Document as below
Document channels = (Document)found.get("disabled_channels")
Then you can access elements in channels using the same get method and cast it as per the need.
I have a MarkLogic XQuery eval call that returns a lists of strings. I use the below code to process the results. I have another call that returns a list of Json Documents but I can't see how to get EvalResult to give me a JsonDocument document. How do I change the below code to process Json Documents?
public static ArrayList<String> getStringList(DatabaseClient client, String query)
{
ArrayList<String> strings = new ArrayList<String>();
ServerEvaluationCall eval = client.newServerEval();
EvalResultIterator eri = eval.xquery(query).eval();
while (eri.hasNext())
{
EvalResult er = eri.next();
String s = er.getString();
strings.add(s);
}
return strings;
}
First, let me suggest that you only use eval as a last resort as it may open a security hole. Injection attacks aren't possible if you never send code from the client to be executed on the server. Start first with the out-of-the-box features, and if those aren't enough, consider writing a resource extension instead of using eval. Two examples are ResourceExtension and JavascriptResourceExtension.
But to answer your question, change this:
String s = er.getString();
to this:
JacksonHandle handle = er.get(new JacksonHandle());
JsonNode json = handle.get();
or this shortcut:
JsonNode json = er.getAs(JsonNode.class);
For a complete example, see handling of myArray and myObject EvalTest.evalAndInvokeXQuery (and of course, runAndTestXQuery) and evaltest.xqy.
These Jackson handles work the same whether you're getting JSON results from a document read, search, or eval. You can read more about the io shortcuts here. For more sample code with Jackson, see JacksonHandleExample, JacksonHandleTest, JacksonStreamTest, and JacksonDatabindTest.
I want to use XStream to convert a java hash to a json hash. I feel like this should be easier than it seems. What I'm looking for is a way to make:
Map<String, String> map = new HashMap<String, String>();
map.put("first", "value1");
map.put("second", "value2");
become
{'first' : 'value1', 'second' : 'value2' }
The closes I have converts it into a series of arrays.
XStream xstream = new XStream(new JettisonMappedXmlDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
xstream.toXML(map);
which becomes
[["first", "value1"], ["second", "value2"]]
I feel like converting a java hash to json hash should be straight forward. Am I missing something?
The thing is that XStream is first and foremost designed to marshal and unmarshal Java objects to XML, JSON being just an afterthought, it most certainly has the least elegant support.
The technical problem being that as XStream must support both - XML and JSON formats, JSON map representation suffers, as there is no native way to represent a map-like structures in XML.
You can try to use the "official" json lib for java from json.org.
Calling:
JSONObject jsobj = new JSONObject(map);
String strJson = jsobj.toString();
I had similar issues when converting to jSon. My solution to this problem was to have the string already formatted to JSon before dropping into the file (in my case a database). The most efficient process I have come up with so far was to create a toJson function inside my classes to work just like toString.
Example:
Converts the objects data output string into Json format
public JsonObject toJson()
{
JsonObject temp = new JsonObject();
temp.addProperty(tagName,floatData);
return temp;
}
So for you, implement a similar process while populating your map.
I am trying to save a set of tags within a mongodb document e.g.
{
id:"104454",
tags:["tag1", "tag2"]
}
I am struggling to figure out how to do this with the Java Driver though. I thought I would use BasicDBList but this doesnt seem to be right.
Could someone help please?
Thanks in advance.
You can use simple arrays and then you can do something like:
doc.put("tags", array)
When saving arrays into MongoDB with Java, according to the online doc, you can use anything that extends List.
So, using your example, that would be something like the following:
ArrayList tags = new ArrayList();
tags.add("tag1");
tags.add("tag2");
BasicDBObject doc = new BasicDBObject(new ObjectId(), tags);
I have Java app that takes data from external app. Incoming JSONs are in Strings. I would like to parse that Strings and create BSON objects.
Unfortunate I can't find API for that in Java's BSON implementation.
Do I have use external parser for that like GSON?
... And, since 3.0.0, you can:
import org.bson.Document;
final Document doc = new Document("myKey", "myValue");
final String jsonString = doc.toJson();
final Document doc = Document.parse(jsonString);
Official docs:
Document.parse(String)
Document.toJson()
Official MongoDB Java Driver comes with utility methods for parsing JSON to BSON and serializing BSON to JSON.
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
DBObject dbObj = ... ;
String json = JSON.serialize( dbObj );
DBObject bson = ( DBObject ) JSON.parse( json );
The driver can be found here: https://mongodb.github.io/mongo-java-driver/
Use Document.parse(String json) from org.bson.Document. It returns Document object which is type of Bson.
The easiest way seems to be to use a JSON library to parse the JSON strings into a Map and then use the putAll method to put those values into a BSONObject.
This answer shows how to use Jackson to parse a JSON string into a Map.
To convert a string json to bson, do:
import org.bson.BasicBSONEncoder;
import org.bson.BSONObject;
BSONObject bson = (BSONObject)com.mongodb.util.JSON.parse(string_json);
BasicBSONEncoder encoder = new BasicBSONEncoder();
byte[] bson_byte = encoder.encode(bson);
To convert a bson to json, do:
import org.bson.BasicBSONDecoder;
import org.bson.BSONObject;
BasicBSONDecoder decoder = new BasicBSONDecoder();
BSONObject bsonObject = decoder.readObject(out);
String json_string = bsonObject.toString();
You might be interested in bson4jackson project, which allows you to use Jackson data binding to work with BSON (create POJOs from BSON, write as BSON) -- especially since Jackson also work with JSON. So it will allow conversion like you mention, just use different ObjectMapper instanstaces (one that works with JSON, other with BSON).
With Jackson you can either work with full POJOs (declare structure you want) or with simple Maps, Lists and so on. You just need to declare what to type to bind to when reading data (when writing, type is defined by object you pass).
You'll find the answer to your question in the source code of https://github.com/mongodb/mongo/blob/master/src/mongo/db/jsobj.cpp
Which has the BSON to JSON conversion.
Basically, stuff like
ObjectId("XXX") -> { "$oid" : "XXX" }
/XXX/gi -> { "$regex" : "XXX", "$options" : "gi" }
and so on...
I would suggest using the toJson() and parse(String) methods of the BasicDBObject, because the JSON utility class has been #Depricated.
import com.mongodb.BasicDBObject;
public static BasicDBObject makeBsonObject(String json) {
return BasicDBObject.parse(json);
}
public static String makeJsonObject(BasicDBObject dbObj) {
return dbObj.toJson();
}
I am not sure about java but the mongoDB CPP driver has a function type
BSONObj fromjson(string)
which returns a BSONObj according to the string passed. There should be a same function in Java too.