当前位置: 首页 > 知识库问答 >
问题:

如何使用jackson ObjectMapper解析MongoDB的UUID对象?

别兴国
2023-03-14

我在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)
}

序列化程序和反序列化程序:

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

共有1个答案

袁子瑜
2023-03-14

您可以使用以下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;
}
 类似资料:
  • 从这里的代码,我只想获得: 我尝试过使用JDT解析我代码,所以我的代码如下所示: 但不管用

  • 这是一个示例文档 我数到50999 当我为匹配条件添加日期字段时,如下所示,我没有得到任何值。 DBObject火柴=new BasicDBObject();match.put("data.type","score.type");match.put("body.name", new BasicDBObject("$存在",1));match.put("时间戳","2014-09-03T22:07:

  • 问题内容: 我正在尝试为我的Django对象获取唯一的ID。在Django 1.8中,它们具有UUIDField。我不确定如何使用此字段来为模型中的每个对象生成唯一的ID。 这是我对UUIDField的要求 我可以重现UUID模型的ID,但是每次我都得到完全相同的ID。:(。 例如: id然后每次都给我相同的id。怎么了,我该如何解决?感谢您的帮助! 问题答案: 我不确定为什么要创建UUID模型。

  • 我需要使用Gson将传入的json消息解析为Java对象。类“MessageBody”应该用于向Gson提供信息。fromJson(json,MessageBody.class); json消息如下所示。 第一层有三个静态字段。第三个字段(“字段”)是“数据字段”对象的列表。 DataField对象有一个类型字段和一个值字段。它的价值可以是异质的。预期类型为:“字符串”、“int”、“布尔”和“H

  • 问题内容: 我有一些JSON数据,但所有键都为大写。如何解析它们并将键转换为更低的键?我正在使用jQuery。 例如: JSON数据: 所需的输出: 问题答案: 这个怎么样: 正则表达式捕获键名$ 1并将其转换为小写。 现场演示:http : //jsfiddle.net/bHz7x/1/ [edit]要解决@FabrícioMatté的评论,另一个仅匹配文字字符的演示: http //jsfid

  • 问题内容: 我有一个域对象Foo,我想解析一些JSON,例如 我想得到一个。像这样 问题答案: 您需要使用来正确表示类型。在这种情况下,由于与泛型类型的交互作用还不够。