如何将Ballerina的原生json转换为javalang.Object`?

j5fpnvbx  于 2023-04-28  发布在  Java
关注(0)|答案(2)|浏览(98)

我有一个函数,它接受的芭蕾舞演员的本机json对象,我想将它传递给一个java函数,我已经用bal bindgen为它创建了芭蕾舞演员绑定。
函数是ObjectMapper.writeValueAsBytes,它接受一个java.lang.Object
如何将json转换为java.lang.Object?换句话说,下面的芭蕾舞演员代码块中的mysteryFunc是什么?

function serialize(json input) returns byte[]|jackson2:JsonProcessingException|error  {
    msgpack:MessagePackMapper mapper = msgpack:newMessagePackMapper1();
    javalang:Object java_obj = mysteryFunc(input);
    return mapper.writeValueAsBytes(java_obj);
}

下面是生成MessagePackMapper类的bindgen命令:

bal bindgen -mvn org.msgpack:jackson-dataformat-msgpack:0.9.3 org.msgpack.jackson.dataformat.MessagePackMapper

编辑:这是我的最新尝试。

import ballerina/io;
import ballerina/websocket;
import ballerina/jballerina.java;

function createJsonHandle(json data) returns handle = @java:Method {
    name: "createHandleValue",
    'class: "io.ballerina.runtime.api.creators.ValueCreator"
} external;

function createMsgpackMapperHandle() returns handle = @java:Constructor {
    'class: "org.msgpack.jackson.dataformat.MessagePackMapper"
} external;

function writeValueAsBytes(handle mapperObj, handle input) 
    returns handle|error = @java:Method {
    'class: "org.msgpack.jackson.dataformat.MessagePackMapper"
} external;

function encode(json input) returns byte[] | error {
    handle mapper = createMsgpackMapperHandle();
    handle input_handle = createJsonHandle(input);
    handle value = check writeValueAsBytes(mapper, input_handle);
    string? str_value = java:toString(value);
    return string:toBytes(str_value ?: "");
}

这样编译,但是我得到了java错误:

error: com.fasterxml.jackson.databind.JsonMappingException {
"message":"iterator cannot be immutable (through reference chain: 
io.ballerina.runtime.internal.values.MapValueImpl["method"]->
io.ballerina.runtime.internal.values.BmpStringValue["iterator"]->
io.ballerina.runtime.internal.values.CharIterator["type"]->
io.ballerina.runtime.internal.types.BIteratorType["immutableType"]
)",
"cause":error(
"io.ballerina.runtime.internal.util.exceptions.BallerinaException",
message="iterator cannot be immutable"
)}
fzsnzjdm

fzsnzjdm1#

AFAIR,您需要通过 Package Ballerina值来创建handle值。然后使用句柄值创建一个Java对象。下面是一个示例代码片段。
没有文档化的方法可以从芭蕾舞演员的值创建句柄。这看起来像是Ballerina中互操作性支持的一个缺口,我们将在未来的版本中修复这个问题。

import ballerina/jballerina.java;
import ballerina/io;

public function main() {
    json j = { "name": "John", "age": 30 };

    // Step 1: Create a handle from the ballerina value
    handle handleResult = createHandle(j);

    // Step 2: Create a new Object instance using the handle
    Object jsonObject = new(handleResult);

    io:println(jsonObject);
}

function createHandle(any data) returns handle = @java:Method {
    name: "createHandleValue",
    'class: "io.ballerina.runtime.api.creators.ValueCreator"
} external;
v7pvogib

v7pvogib2#

按照代码,它使用Jacksondatabind序列化通过java互操作函数传递的芭蕾舞者json对象。序列化器将序列化给定ballerina json本机对象的整个对象层次结构。因此,除了JSON内容之外,它还会尝试序列化类型相关的对象。
在序列化过程中,它将调用与给定json数据关联的对象字段的所有Java getter。因此序列化器尝试在处理过程中从迭代器类型调用'getImmutableType'方法,因为芭蕾舞者字符串包含迭代器。由于芭蕾舞演员迭代器不可能是不可变的,它将抛出异常。
正常的芭蕾舞演员程序在迭代器运行时永远不会调用'getImmutableType'方法。我们实际上并不需要序列化与JSON数据相关联的类型和其他Java对象,只需要序列化内容。
一种选择是使用Jacksondatabind定制序列化逻辑。另一个选择是使用ballerina/serdes模块,如下所示。

import ballerina/io;
import ballerina/serdes;

type Student record {
    int id;
    string name;
    decimal fees;
};

public function main() returns error? {
    json jsonValue = {
        id: 7894,
        name: "Waruna",
        fees: 24999.99
    };
    Student studentValue = check jsonValue.cloneWithType(Student);
    serdes:Proto3Schema serdes = check new (Student);
    byte[] serializedValue = check serdes.serialize(studentValue);
    Student deserializedValue = check 
    serdes.deserialize(serializedValue);
    io:println(deserializedValue);
}

这里芭蕾舞者serdes目前不支持json直接按照[1],所以我们需要Map到一个记录并获取字节。
[1][https://github.com/ballerina-platform/ballerina-standard-library/issues/4386](https://github.com/ballerina-platform/ballerina-standard-library/issues/4386)

相关问题