Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-3292

Add a Codec for converting directly to and from a JSON string

    • Type: Icon: New Feature New Feature
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.2.0
    • Affects Version/s: None
    • Component/s: JSON
    • None
    • Needed
    • Hide

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

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

      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()))
      

            Assignee:
            brian.deleonardis@mongodb.com Brian DeLeonardis (Inactive)
            Reporter:
            jeff.yemin@mongodb.com Jeffrey Yemin
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: