我在MongoDB集合sample
中有以下文档,我想将该文档映射回Kotlin对象Sample
。
我编写了一个自定义反序列化器以读取UUID的二进制值,但是失败。任何帮助将不胜感激。
db.signals.findOne():
/* 1 */
{
"_id" : ObjectId("5deb5bb749772bab4217199e"),
"name" : "Tom",
"sampleId" : LUUID("6b48b8d3-b64f-cfae-9df1-76dd01933281")
}
Sample.kt
@JsonIgnoreProperties(ignoreUnknown = true)
class Sample @JsonCreator constructor(
@JsonProperty("name")var name: String) {
@JsonProperty("sampleId") val sampleId = UUID.randomUUID();
}
主应用。
fun main() {
val config = loadConfig()
val mongoClientURI = config.mongodb;
val mongoClient = MongoClients.create(mongoClientURI);
val db = mongoClient.getDatabase("db");
val objectMapper = ObjectMapper();
val module = SimpleModule();
module.addSerializer(UUID::class.java, mongo.UUIDSerializer)
module.addDeserializer(UUID::class.java, mongo.UUIDDeserializer)
objectMapper.registerModule(module);
val samples = db.getCollection("sample"); //Document{{_id=5deb5bb749772bab4217199e, name=Tom, sampleId=aecf4fb6-d3b8-486b-8132-9301dd76f19d}}
val sampleDoc: Document? = samples.findOne();
println(sampleDoc)
val sample = objectMapper.readValue(sampleDoc?.toJson(), Sample::class.java);
println(sample)
}
异常堆栈跟踪:
线程“ main”中的异常com.fasterxml.jackson.databind.JsonMappingException:当前令牌(START_OBJECT)不是VALUE_STRING或VALUE_EMBEDDED_OBJECT,不能作为二进制文件访问 在[来源:(String)“ {” _ id“:{” $ oid“:” 5deb5bb749772bab4217199e“},” name“:” Tom“,” sampleId“:{” $ binary“:” a0i407ZPz66d8XbdAZMygQ ==“,” $类型“:” 03“}}”;行:1,列:74](通过参考链:mongodb.Sample [“ sampleId”]) 在com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394) 在com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353) 在com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1714) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:254) 在com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:441) 在com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1287) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) 在com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202) 在com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205) 在com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173) 在mongodb.MongoKt.main(mongo.kt:70) 在mongodb.MongoKt.main(mongo.kt) 引起原因:com.fasterxml.jackson.core.JsonParseException:当前令牌(START_OBJECT)不是VALUE_STRING或VALUE_EMBEDDED_OBJECT,不能作为二进制文件访问 在[来源:(String)“ {” _ id“:{” $ oid“:” 5deb5bb749772bab4217199e“},” name“:” Tom“,” sampleId“:{” $ binary“:” a0i407ZPz66d8XbdAZMygQ ==“,” $类型“:” 03“}}”;行:1,列:75] com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1840) 在com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:712) 在com.fasterxml.jackson.core.json.ReaderBasedJsonParser.getBinaryValue(ReaderBasedJsonParser.java:467) 在com.fasterxml.jackson.core.JsonParser.getBinaryValue(JsonParser.java:1484) 在mongodb.mongo $ UUIDDeserializer.deserialize(mongo.kt:41) 在mongodb.mongo $ UUIDDeserializer.deserialize(mongo.kt:39) 在com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138) 在com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:252) ...还有9个
序列化器和反序列化器:
class mongo {
companion object {
fun getBytesFromUUID(uuid: UUID): ByteArray {
val bb: ByteBuffer = ByteBuffer.wrap(ByteArray(16))
bb.putLong(uuid.mostSignificantBits)
bb.putLong(uuid.leastSignificantBits)
return bb.array()
}
fun getUUIDFromBytes(bytes: ByteArray): UUID {
val byteBuffer: ByteBuffer = ByteBuffer.wrap(bytes)
val high: Long = byteBuffer.getLong()
val low: Long = byteBuffer.getLong()
return UUID(high, low)
}
}
object UUIDDeserializer : StdDeserializer<UUID>(UUID::class.java) {
override fun deserialize(parser: JsonParser, deserializer: DeserializationContext): UUID {
val binary: ByteArray = parser.binaryValue
val uuid = getUUIDFromBytes(binary);
return uuid;
}
}
object UUIDSerializer : StdSerializer<UUID>(UUID::class.java) {
override fun serialize(uuid: UUID, jsonGenerator: JsonGenerator, serializerProvider: SerializerProvider) {
jsonGenerator.writeBinary(getBytesFromUUID(uuid))
}
}
}
答案 0 :(得分:1)
您可以使用以下Jackson自定义序列化器和反序列化器来处理到Java UUID的转换:
LUUID序列化程序
/**
* Jackson serializer for MongoDB legacy UUIDs. An LUUID is composed of a Base64 encoded UUID, and a type.
*
* <p><p><p>
* Example as JSON serialized string:
* <pre>
* {@code
* {"$binary": "a0i407ZPz66d8XbdAZMygQ==", "$type": "03"}
* }
* </pre>
*/
public class LegacyUuidSerializer extends StdSerializer<UUID> {
public LegacyUuidSerializer() {
super(UUID.class);
}
@Override
public void serialize(UUID value, JsonGenerator generator, SerializerProvider provider) throws IOException {
byte[] bytes = new byte[16];
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.putLong(value.getMostSignificantBits());
byteBuffer.putLong(value.getLeastSignificantBits());
String base64EncodedUuid = Base64.getEncoder().encodeToString(bytes);
generator.writeStartObject();
generator.writeStringField("$binary", base64EncodedUuid);
generator.writeStringField("$type", "03"); // Assume always type 3.
generator.writeEndObject();
}
}
LUUID反序列化器
/**
* Jackson deserializer for MongoDB legacy UUIDs. An LUUID is composed of a Base64 encoded UUID, and a type.
*
* <p><p><p>
* Example as JSON serialized string:
* <pre>
* {@code
* {"$binary": "a0i407ZPz66d8XbdAZMygQ==", "$type": "03"}
* }
* </pre>
*/
public class LegacyUuidDeserializer extends StdDeserializer<UUID> {
public LegacyUuidDeserializer() {
super(UUID.class);
}
@Override
public UUID deserialize(JsonParser parser, DeserializationContext context) throws IOException {
parser.nextToken(); // $binary
parser.nextToken(); // Base64 encoded UUID.
String base64EncodedUuid = parser.getText();
parser.nextToken(); // $type
parser.nextToken(); // $type value, e.g. 03
byte[] bytes = Base64.getDecoder().decode(base64EncodedUuid);
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
long mostSigBits = byteBuffer.getLong();
long leastSigBits = byteBuffer.getLong();
return new UUID(mostSigBits, leastSigBits);
}
}
域对象
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Sample {
private String name;
@JsonSerialize(using = LegacyUuidSerializer.class)
@JsonDeserialize(using = LegacyUuidDeserializer.class)
private UUID sampleId;
}