[JAVA-3292] Add a Codec for converting directly to and from a JSON string Created: 17/May/19  Updated: 28/Oct/23  Resolved: 14/Sep/20

Status: Closed
Project: Java Driver
Component/s: JSON
Affects Version/s: None
Fix Version/s: 4.2.0

Type: New Feature Priority: Major - P3
Reporter: Jeffrey Yemin Assignee: Brian DeLeonardis (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Documented
Case:
Documentation Changes: Needed
Documentation Changes Summary:

Documentation changes have been made as part of the commit, but will need to be ported over to the new documentation site.


 Description   

Some applications of MongoDB don't have need of the intermediate map structure provided by Document. Of those, some just need to shuttle around raw BSON, and for that there is RawBsonDocument. Others just want to traffic in JSON, and the best we can do for them now is a bit heavyweight: decode to Document and call its toJson method. This has two problems

  • Applications have to pay for an intermediate Map that they don't need
  • Applications wishing to customize via JsonWriterSettings have to pass the settings as a parameter to each toJson call.

The first problem can be alleviated by decoding to RawBsonDocument instead, but

  • That's not so intuitive
  • It results in an extra copy of the raw bytes

We can do better by introducing a new class that wraps a JSON string, and a Codec for it that is customizable with its own JsonWriterSettings. It would look something like this:

// Simple wrapping class
public class JsonObject {
    private final String json;
 
    public JsonObject(final String json) {
        this.json = json;
    }
 
    public String getJson() {
        return json;
    }
 
    @Override
    public String toString() {
        return json;
    }
}

// Codec for JsonObject
public class JsonObjectCodec implements Codec<JsonObject> {
 
    private final JsonWriterSettings writerSettings;
 
    public JsonStringCodec() {
        this(JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build());
    }
 
    public JsonStringCodec(final JsonWriterSettings writerSettings) {
        this.writerSettings = writerSettings;
    }
 
    @Override
    public JsonObject decode(final BsonReader bsonReader, final DecoderContext decoderContext) {
        StringWriter stringWriter = new StringWriter();
        new JsonWriter(stringWriter, writerSettings).pipe(bsonReader);
        return new JsonString(stringWriter.toString());
    }
 
    @Override
    public void encode(final BsonWriter bsonWriter, final JsonObject jsonObject, final EncoderContext encoderContext) {
        bsonWriter.pipe(new JsonReader(jsonString.getJson()));
    }
 
    @Override
    public Class<JsonObject> getEncoderClass() {
        return JsonObject.class;
    }
}

If we add this to the default codec registry, then applications can just do:

        var coll = client.getDatabase("test").getCollection("test", JsonString.class);
        // res is of type List<JsonString>
        var res = coll.find().into(new ArrayList<>());

To customize the Codec, just register your own instance in the registry:

                MongoClientSettings.builder()
                        .codecRegistry(fromRegistries(
                                fromCodecs(
                                        new JsonObjectCodec(JsonWriterSettings
                                                .builder()
                                                .outputMode(JsonMode.RELAXED)
                                                .objectIdConverter((objectId, strictJsonWriter) -> {
                                                    strictJsonWriter.writeString(objectId.toHexString());
                                                })
                                                .build())),
                                getDefaultCodecRegistry()))



 Comments   
Comment by Githook User [ 11/Sep/20 ]

Author:

{'name': 'Brian DeLeonardis', 'email': 'bdeleonardis1@gmail.com', 'username': 'bdeleonardis1'}

Message: Add JsonObjectCodec for efficient JSON encoding/decoding

JAVA-3292
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/151624192ecbabcfc8ebd8d33487c4e8b53aea40

Generated at Thu Feb 08 08:59:15 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.