protobuf-java中的一些小技巧
阿新 • • 發佈:2019-02-03
1、json字串和pb物件之間的轉換:
1)pom.xml
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>com.googlecode.protobuf-java-format</groupId> <artifactId>protobuf-java-format</artifactId> <version>1.2</version> </dependency>
2)pb訊息定義:
option java_package = "com.abc.proto";
option java_outer_classname="HelloWordPB";
message HelloWord {
optional int64 id = 1;
optional string name = 2;
repeated string recId = 3;
}
3)java程式碼:
public class PBTest { public static void main(String[] args) { JSONObject jo = new JSONObject(); JSONArray ja = new JSONArray(); ja.add("1"); ja.add("2"); jo.put("id", 123456);//這裡不能是字串型別,否則pb會報錯 jo.put("name", "test"); jo.put("recId", ja); String jsonStr = jo.toJSONString(); System.out.println(jsonStr); //json > pb Builder newBuilder = HelloWordPB.HelloWord.newBuilder(); try { JsonFormat.merge(jsonStr, newBuilder); System.out.println(newBuilder.build().toString()); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } //pb > json String printToString = JsonFormat.printToString(newBuilder.build()); System.out.println(printToString); } }
輸出:
{"name":"test","id":123456,"recId":["1","2"]}
id: 123456
name: "test"
recId: "1"
recId: "2"
{"id": 123456,"name": "test","recId": ["1","2"]}
2、toString於pb物件之間轉換:
public static void main(String...strings) { Builder newBuilder = ApiLogPB.ApiLog.newBuilder(); newBuilder.setCost(10); newBuilder.setChId("default"); newBuilder.setReqId("reqid"); newBuilder.setFNum(12); newBuilder.setPuid("puid"); newBuilder.setUId("uid"); ApiLog apiLog = newBuilder.build(); String string = apiLog.toString(); System.out.println(string); System.out.println("--------------------------"); Builder newBuilder2 = ApiLogPB.ApiLog.newBuilder(); try { TextFormat.merge(string, newBuilder2); } catch (ParseException e) { e.printStackTrace(); } String chId = newBuilder2.getChId(); System.out.println(chId); }
輸出:
puid: "puid"
uId: "uid"
reqId: "reqid"
fNum: 12
cost: 10
chId: "default"
--------------------------
default
3、從檔案中構建pb物件:
1)pb結構
option java_package="com.lanjingling.cinema";
enum MovieType{
CHILDREN=1;
ADULT=2;
NORMAL=3;
OHTER=4;
}
message Movie{
required string name=1;
required MovieType type=2;
optional int32 releaseTimeStamp=3;
optional string description=4;
}
message Ticket{
required int32 id=1;
repeated Movie movie=2;
optional Customer customer=3;
}
2)構建pb物件,tostring輸出到檔案:
public class Test {
public static void main(String[] args) throws Exception {
Cinema.Movie.Builder movieBuilder = Cinema.Movie.newBuilder();
movieBuilder.setName("The Shining");
movieBuilder.setType(Cinema.MovieType.ADULT);
movieBuilder.setReleaseTimeStamp(327859200);
Movie movie = movieBuilder.build();
Cinema.Movie.Builder movieBuilder1 = Cinema.Movie.newBuilder();
movieBuilder1.setName("The Shining1");
movieBuilder1.setType(Cinema.MovieType.CHILDREN);
movieBuilder1.setReleaseTimeStamp(327859201);
Movie movie1 = movieBuilder1.build();
Cinema.Ticket.Builder ticketBuilder = Cinema.Ticket.newBuilder();
ticketBuilder.setId(1);
ticketBuilder.addMovie(movie);
ticketBuilder.addMovie(movie1);
Ticket ticket = ticketBuilder.build();
System.out.println(ticket.toString());
}
}
將輸出儲存到cineme.txt檔案。內容如下:
id: 1
movie {
name: "The Shining"
type: ADULT
releaseTimeStamp: 327859200
}
movie {
name: "The Shining1"
type: CHILDREN
releaseTimeStamp: 327859201
}
3)從檔案中讀取資料,反序列化:
public class Test2 {
public static void main(String[] args) throws Exception {
Cinema.Ticket.Builder ticketBuilder = Cinema.Ticket.newBuilder();
InputStream inputStream = new FileInputStream("D://cinema.txt");
TextFormat.merge(new InputStreamReader(inputStream), ticketBuilder);
Ticket ticket = ticketBuilder.build();
System.out.println(ticket);
}
}
4、pb在構造Builder的時候可以傳入一個pb物件:
1)假設我們從redis中讀取了一個pb二進位制資料,然後反序列化成pb物件:
com.abc.proto.UserRecHistoryPB.UserRecHistory userRecHistory = null;
String KEY = MessageFormat.format(CacheConstants.CACHE_KEY_USER_HISTORY_PERF, deviceId);
byte[] bs = couchbaseHistoryDao.get(KEY);
if (bs != null) {
userRecHistory = UserRecHistoryPB.UserRecHistory.parseFrom(bs);
}
2)接下來對userRecHistory進行修改,修改完畢後需要再儲存到redis中:
Builder recHistoryBuilder = UserRecHistoryPB.UserRecHistory.newBuilder(userRecHistory);
//修改
UserRecHistory build = recHistoryBuilder.build();
String KEY = MessageFormat.format(CacheConstants.CACHE_KEY_USER_HISTORY_PERF, deviceId);
int ttl = (int)(System.currentTimeMillis()/1000)+CacheConstants.CACHE_TIME_QUARTER;
couchbaseHistoryDao.set(KEY,
ttl,
build.toByteArray());
4、pb克隆:
pb的newBuilder就是一個深拷貝,類似於thrift的deepCopy();
Builder newBuilder = ApiLogPB.ApiLog.newBuilder();
newBuilder.setCost(10);
newBuilder.setChId("default");
newBuilder.setReqId("reqid");
newBuilder.setFNum(12);
newBuilder.setPuid("puid");
newBuilder.setUId("uid");
ApiLog apiLog = newBuilder.build();
//-----------
Builder newBuilder22 = apiLog.newBuilder();//深拷貝
類似於thtrift的:
InnerRequest pbdReq = innerRequest.deepCopy();