Java Bson库如何将BsonArray等单个BsonValue转换为JSON字符串?
问题
开发MongoDB ChangStream导入AWS Redshift功能时,需要将MongoDB中的复合字段类型(如BsonArray、BsonDocument)转换为JSON字符串。Java Bson库仅支持通过toJson方法将BsonDocument转换为JSON字符串,但BsonArray等其他复合字段类型没有直接的转换方法。
示例代码:
BsonArray bsonArray = new BsonArray(); bsonArray.add(new BsonString("apple")); bsonArray.add(new BsonString("banana")); bsonArray.add(new BsonString("orange"));
期望输出:
["apple","banana","orange"]
尝试了以下代码:
BsonArray bsonArray = new BsonArray(); bsonArray.add(new BsonString("apple")); bsonArray.add(new BsonString("banana")); bsonArray.add(new BsonString("orange")); StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.writeStartArray(); for (int i = 0; i < bsonArray.size(); i++) { jsonWriter.writeString(bsonArray.get(i).toString()); } jsonWriter.writeEndArray(); jsonWriter.flush(); String jsonString = stringWriter.toString(); System.out.println("JSON: " + jsonString);
但抛出异常:
Exception in thread "main" org.bson.BsonInvalidOperationException: A StartArray value cannot be written to the root level of a BSON document.
解决方案
方法一:利用CodecRegistry直接编码BsonArray
报错原因是默认的JsonWriter以BSON文档模式工作,不允许根节点为数组。通过配置JsonWriter为JSON输出模式,并利用BsonArrayCodec完成编码,可以正确输出JSON数组:
import org.bson.BsonArray; import org.bson.BsonString; import org.bson.codecs.BsonArrayCodec; import org.bson.codecs.BsonValueCodecProvider; import org.bson.codecs.EncoderContext; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.json.JsonMode; import org.bson.json.JsonWriter; import org.bson.json.JsonWriterSettings; import java.io.StringWriter; public class BsonArrayToJson { public static void main(String[] args) { BsonArray bsonArray = new BsonArray(); bsonArray.add(new BsonString("apple")); bsonArray.add(new BsonString("banana")); bsonArray.add(new BsonString("orange")); StringWriter stringWriter = new StringWriter(); // 配置JsonWriter为JSON输出模式 JsonWriter jsonWriter = new JsonWriter(stringWriter, JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build()); // 注册BsonValue的Codec CodecRegistry registry = CodecRegistries.fromProviders(new BsonValueCodecProvider()); BsonArrayCodec arrayCodec = registry.get(BsonArray.class); // 编码BsonArray到JsonWriter arrayCodec.encode(jsonWriter, bsonArray, EncoderContext.builder().build()); String jsonString = stringWriter.toString(); System.out.println(jsonString); // 输出 ["apple","banana","orange"] } }
方法二:使用新版本MongoDB Java驱动的toJson方法
如果使用的是MongoDB Java驱动3.8及以上版本,BsonArray继承的BsonValue接口已经提供了toJson()方法,可以直接调用:
BsonArray bsonArray = new BsonArray(); bsonArray.add(new BsonString("apple")); bsonArray.add(new BsonString("banana")); bsonArray.add(new BsonString("orange")); String jsonString = bsonArray.toJson(); System.out.println(jsonString); // 输出 ["apple","banana","orange"]
方法三:临时包裹BsonArray到BsonDocument(兼容旧版本)
如果无法升级驱动,可以将BsonArray放到一个临时的BsonDocument中,调用toJson后再裁剪掉外层的键值对:
BsonArray bsonArray = new BsonArray(); bsonArray.add(new BsonString("apple")); bsonArray.add(new BsonString("banana")); bsonArray.add(new BsonString("orange")); // 用临时键包裹数组 BsonDocument tempDoc = new BsonDocument("temp", bsonArray); String tempJson = tempDoc.toJson(); // 裁剪掉外层的{"temp": 和 } String jsonString = tempJson.substring(8, tempJson.length() - 1); System.out.println(jsonString); // 输出 ["apple","banana","orange"]
内容的提问来源于stack exchange,提问作者冲天炮
相关产品推荐
相关产品推荐

