java和Js中的类型转换_graalvm js 与java 类型转换的一些方法

在基于跨不同语言的通信开发中,数据类型的转换是一个很大的部分,目前来说graalvm 对于java host 类型与js 对象类似的转换还是不够好

java host 对象到js 的操作我们可以通过ProxyObject 以及提供的HostAccess 注解处理

参考模式

js 到java 对象转换

这个对应的数据类型还是比较多的,比如普通类型以及java 的pojo 类型

简单类型,graalvm 已经提供了as 方法,但是不是很好的地方是当前不支持直接到pojo,我们需要转换为其他支持的类型再处理,一般我们

日常会使用到的类型有array,string,int,object 。。。。,为了方便我们可以结合 jackson-databind 来处理类型转换

pojo 的我们解决map 类型到pojo 的转换处理

参考代码

Value execResult =result.execute(ProxyObject.fromMap(ob),filed);

Map results = execResult.as(Map.class);

System.out.println("demoappa"+execResult.as(List.class));

ObjectMapper objectMapper = new ObjectMapper();

CollectionType javaType = objectMapper.getTypeFactory()

.constructCollectionType(List.class, MyUser.class);

List myusers = execResult.as(List.class);

System.out.println("myusers"+myusers);

ArrayList users = objectMapper.convertValue(myusers, javaType);

System.out.println("dalong"+users);

Array 类型的转换:

通过Value 提供的as List 转换

Value execResult =result.execute(ProxyObject.fromMap(ob),filed);

Map results = execResult.as(Map.class);

ObjectMapper objectMapper = new ObjectMapper();

CollectionType javaType = objectMapper.getTypeFactory()

.constructCollectionType(List.class, MyUser.class);

List extends Object> myusers = execResult.as(List.class);

System.out.println("myusers---"+(List)myusers);

ArrayList users = objectMapper.convertValue(myusers, javaType);

System.out.println("dalong"+users);

目前内部转换的支持代码(后期可能会变)

@TruffleBoundary

private static T asJavaObject(Object value, Class targetType, Type genericType, boolean allowsImplementation, PolyglotLanguageContext languageContext) {

Objects.requireNonNull(value);

InteropLibrary interop = InteropLibrary.getFactory().getUncached(value);

Object obj;

if (interop.isNull(value)) {

if (targetType.isPrimitive()) {

throw HostInteropErrors.nullCoercion(languageContext, value, targetType);

}

return null;

} else if (HostObject.isJavaInstance(targetType, value)) {

obj = HostObject.valueOf(value);

} else if (targetType == Object.class) {

obj = convertToObject(value, languageContext, interop);

} else if (targetType == List.class) {

if (interop.hasArrayElements(value)) {

boolean implementsFunction = shouldImplementFunction(value, interop);

TypeAndClass> elementType = getGenericParameterType(genericType, 0);

obj = PolyglotList.create(languageContext, value, implementsFunction, elementType.clazz, elementType.type);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have array elements.");

}

} else if (targetType == Map.class) {

Class> keyClazz = getGenericParameterType(genericType, 0).clazz;

TypeAndClass> valueType = getGenericParameterType(genericType, 1);

if (!isSupportedMapKeyType(keyClazz)) {

throw newInvalidKeyTypeException(keyClazz);

}

boolean hasSize = (Number.class.isAssignableFrom(keyClazz)) && interop.hasArrayElements(value);

boolean hasKeys = (keyClazz == Object.class || keyClazz == String.class) && interop.hasMembers(value);

if (hasKeys || hasSize) {

boolean implementsFunction = shouldImplementFunction(value, interop);

obj = PolyglotMap.create(languageContext, value, implementsFunction, keyClazz, valueType.clazz, valueType.type);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have members or array elements.");

}

} else if (targetType == Function.class) {

TypeAndClass> returnType = getGenericParameterType(genericType, 1);

if (interop.isExecutable(value) || interop.isInstantiable(value)) {

obj = PolyglotFunction.create(languageContext, value, returnType.clazz, returnType.type);

} else if (interop.hasMembers(value)) {

obj = HostInteropReflect.newProxyInstance(targetType, value, languageContext);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must be executable or instantiable.");

}

} else if (targetType.isArray()) {

if (interop.hasArrayElements(value)) {

obj = truffleObjectToArray(interop, value, targetType, genericType, languageContext);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have array elements.");

}

} else if (targetType == LocalDate.class) {

if (interop.isDate(value)) {

try {

obj = interop.asDate(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have date and time information.");

}

} else if (targetType == LocalTime.class) {

if (interop.isTime(value)) {

try {

obj = interop.asTime(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have date and time information.");

}

} else if (targetType == LocalDateTime.class) {

if (interop.isDate(value) && interop.isTime(value)) {

LocalDate date;

LocalTime time;

try {

date = interop.asDate(value);

time = interop.asTime(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

obj = createDateTime(date, time);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have date and time information.");

}

} else if (targetType == ZonedDateTime.class) {

if (interop.isDate(value) && interop.isTime(value) && interop.isTimeZone(value)) {

LocalDate date;

LocalTime time;

ZoneId timeZone;

try {

date = interop.asDate(value);

time = interop.asTime(value);

timeZone = interop.asTimeZone(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

obj = createZonedDateTime(date, time, timeZone);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have date, time and time-zone information.");

}

} else if (targetType == ZoneId.class) {

if (interop.isTimeZone(value)) {

try {

obj = interop.asTimeZone(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have time-zone information.");

}

} else if (targetType == Instant.class || targetType == Date.class) {

if (interop.isDate(value) && interop.isTime(value) && interop.isTimeZone(value)) {

Instant instantValue;

try {

instantValue = interop.asInstant(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

if (targetType == Date.class) {

obj = Date.from(instantValue);

} else {

obj = targetType.cast(instantValue);

}

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have date, time and time-zone information.");

}

} else if (targetType == Duration.class) {

if (interop.isDuration(value)) {

try {

obj = interop.asDuration(value);

} catch (UnsupportedMessageException e) {

throw shouldNotReachHere(e);

}

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have duration information.");

}

} else if (targetType == PolyglotException.class) {

if (interop.isException(value)) {

obj = asPolyglotException(value, interop, languageContext);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must be an exception.");

}

} else if (allowsImplementation && targetType.isInterface()) {

if (HostInteropReflect.isFunctionalInterface(targetType) && (interop.isExecutable(value) || interop.isInstantiable(value))) {

obj = HostInteropReflect.asJavaFunction(targetType, value, languageContext);

} else if (interop.hasMembers(value)) {

obj = HostInteropReflect.newProxyInstance(targetType, value, languageContext);

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Value must have members.");

}

} else {

throw HostInteropErrors.cannotConvert(languageContext, value, targetType, "Unsupported target type.");

}

assert targetType.isInstance(obj);

return targetType.cast(obj);

}

java host object && meethod 2 js

对于object 类型,比较推荐的是通过ProxyObject 进行map转换处理(对应到js 的object)

java 代码:

Map ob =new HashMap<>();

Map ob2 =new HashMap<>();

ob2.put("url","https://plus.google.com/102817283354809142195/posts/F97fqZwJESL");

ob.put("url","https://plus.google.com/102817283354809142195/posts/F97fqZwJESL");

Map ob3 =new HashMap<>();

ob3.put("url","https://plus.google.com/102817283354809142195/posts/F97fqZwJESL");

ob2.put("ob",ProxyObject.fromMap(ob3));

ob.put("id","z12gtjhq3qn2xxl2o224exwiqruvtda0i");

ob.put("object",ProxyObject.fromMap(ob2));

js 代码:

window = this || {}

window.demo = function (datas, fields) {

let mydatas

mydatas = datas;

if (typeof datas === 'string') {

mydatas =JSON.parse(datas)

}

return mask(mydatas, fields)

}

普通java对象通过 @HostAccess 注解暴露

public class Dalong {

@HostAccess.Export

public   String  username;

@HostAccess.Export

public   String  password;

@HostAccess.Export

public  String token() {

return String.format("%s------%s",this.username,this.password);

}

}

使用

Dalong dalong = new Dalong();

dalong.password="dalong";

dalong.username="dalong";

Context context = Context.newBuilder().allowAllAccess(true).allowHostClassLoading(true).allowHostAccess(hostAccess).allowIO(true).allowNativeAccess(true).engine(engine).build();

context.getBindings("js").putMember("mydalong",dalong);

System.out.println(context.getBindings("js").getMemberKeys());

String myjs = "mydalong.username= \"dalongdemossss\";\n" +

"mydalong.password= \"deeeeeeee\";\n" +

"\n" +

"console.log(\"my token\",mydalong.token())\n" +

"\n";

context.eval("js",myjs);

说明

以上是一些自己简单的整理,实际应该还会有其他更方便的方法,graalvm 的js 能力很强大,很值得使用

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值