protobuf java object_protobuf 与 Java 对象互转

Java使用protobuf时,往往需要在Java对象(比如POJO)和protobuf message的Java对象间互转:

protobuf接口需要传入message参数: 把POJO转成message, 作为接口参数;

protobuf接口会返回message参数: 需要把message转成POJO, 供后续使用.

比如:

protobuf的message

message HelloRequest {

string name = 1;

int32 type = 2;

string location = 3;

bool flag = 4;

}

Java的POJO:

@Getter

@Setter

@ToString

public class HelloDTO {

private String name;

private Integer type;

private String location;

private Boolean flag;

private String message;

}

POJO -> Message

Hello.HelloRequest.Builder builder = Hello.HelloRequest.newBuilder();

builder.setFlag(true);

builder.setName("Name1");

builder.setLocation("Location1");

builder.setType(1);

Hello.HelloRequest request = builder.build();

Message -> POJO

Hello.HelloRequest request;

HelloDTO hello = new HelloDTO();

hello.setFlag(request.getFlag());

hello.setName(request.getName());

hello.setLocation(request.getLocation());

hello.setType(request.getType());

可以想象, 在protobuf定义的message很多的情况下,这些代码写起来费时费力, 还容易遗漏,有什么好的方法可以解决这个问题呢?

实际上POJO与PB Message之间的转换, 类似于POJO与Json之间的转换, 所以可以把上述过程简化:

message -> POJO: 对于POJO中任一属性,只有message中也有时, 才取出来设置.

/**

* ProtoBuffer object to POJO

*/

private static T fromProtoBuffer(GeneratedMessageV3 pbObject, Class modelClass) {

T model = null;

try {

model = modelClass.newInstance();

Field[] modelFields = modelClass.getDeclaredFields();

if (modelFields != null && modelFields.length > 0) {

for (Field modelField : modelFields) {

String fieldName = modelField.getName();

String name = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

Class> fieldType = modelField.getType();

try {

Method pbGetMethod = pbObject.getClass().getMethod("get" + name);

Object value = pbGetMethod.invoke(pbObject);

Method modelSetMethod = modelClass.getMethod("set" + name, fieldType);

modelSetMethod.invoke(model, value);

} catch (NoSuchMethodException e) {

e.printStackTrace();

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

return model;

}

POJO -> message: 对于message中任一属性,只有POJO中也有时, 才取出来设置.

/**

* POJO -> ProtoBuffer object

*/

private static T toProtoBuffer(Object model, Class pbClass) {

if (!GeneratedMessageV3.class.isAssignableFrom(pbClass)) {

throw new RuntimeException("Not ProtoBuffer message type");

}

T pbObject = null;

try {

Object pbBuilder = pbClass.getDeclaredMethod("newBuilder").invoke(null);

Field[] pbFields = pbClass.getDeclaredFields();

if (pbFields != null && pbFields.length > 0) {

for (Field pbField : pbFields) {

String fieldName = pbField.getName().substring(0, pbField.getName().length() - 1);

String name = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

Class> fieldType = pbField.getType();

if (pbField.getType() == Object.class) {

fieldType = String.class;

}

try {

Method modelGetMethod = model.getClass().getMethod("get" + name);

Object value = modelGetMethod.invoke(model);

if (value != null) {

Method pbBuilderSetMethod = pbBuilder.getClass().getMethod("set" + name, fieldType);

pbBuilderSetMethod.invoke(pbBuilder, value);

}

} catch (NoSuchMethodException e) {

e.printStackTrace();

}

}

}

pbObject = (T) pbBuilder.getClass().getDeclaredMethod("build").invoke(pbBuilder);

} catch (Exception e) {

e.printStackTrace();

}

return pbObject;

}

以上代码仅为示例代码(demo), 实际使用时往往message和POJO分别都是嵌套的, 因此需要略有调整.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值