programing

Json에서 Protobuf로 변환하는 방법?

cafebook 2023. 3. 14. 21:54
반응형

Json에서 Protobuf로 변환하는 방법?

protobuf를 처음 사용하는데 자바에서 json stream/string을 protobuf stream/string으로 간단하게 변환할 수 있는 방법이 없을까요?

예를들면,

protoString = convertToProto(jsonString)

protobuf 메시지로 해석하는 json 문자열이 있습니다.그래서 먼저 json 문자열을 protobuf로 변환하고 나서Message.parseFrom()그 위에 올려놔요.

proto3에서는 JsonFormat을 사용하여 이를 수행할 수 있습니다.JSON 표현에서 직접 해석되므로 별도로 호출할 필요가 없습니다.MyMessage.parseFrom(...). 다음과 같은 것이 작동해야 합니다.

JsonFormat.parser().merge(json_string, builder);
//You can use this for converting your input json to a Struct / any other Protobuf Class    

import com.google.protobuf.Struct.Builder;
import com.google.protobuf.Struct;
import com.google.protobuf.util.JsonFormat;
import org.json.JSONObject;

JSONObject parameters = new JSONObject();

Builder structBuilder = Struct.newBuilder();
JsonFormat.parser().merge(parameters.toString(), structBuilder);

// Now use the structBuilder to pass below (I used it for Dialog Flow V2 Context Management)

어떤 사람이 "com.google.protobuf" 예외에 대해 물어봤기 때문에Adam의 조언을 따를 때 InvalidProtocolBufferException: JsonObject"와 같은 문제가 발생하였습니다.구글 프로토부프 타임스탬프 때문인 것으로 드러났습니다.seconds 와 nanos 의 2 개의 필드를 포함한 오브젝트로 시리얼화 됩니다.이것은 프로덕션 코드가 아니기 때문에, 잭슨을 사용해 JSON 를 해석해, JSON 오브젝트를 재귀적으로 조사해, 오브젝트의 모든 타임스탬프를 RFC 3339 에 따라서 포맷 된 문자열로 변경해, 그것을 시리얼화해, 프로토를 사용했습니다.Adam이 나타낸 바와 같이 buf JSON 파서.이것으로 문제가 해결되었습니다.이것은 제가 작성한 일회용 코드입니다(모든 타임스탬프 필드에 "timestamp"라는 단어가 포함되어 있습니다.이것이 더 강력할 수 있지만, 저는 상관없습니다).

public Map<String, Object> fixJsonTimestamps(Map<String, Object> inMap) {
    Map<String, Object> outMap = new HashMap<>();
    for(String key : inMap.keySet()) {
        Object val = inMap.get(key);
        if(val instanceof Map) {
            Map<String, Object> valMap = (Map<String, Object>)val;
            if(key.toLowerCase().contains("timestamp") && 
                    valMap.containsKey("seconds") && valMap.containsKey("nanos")) {
                if(valMap.get("seconds") != null) {
                    ZonedDateTime d = ZonedDateTime.ofInstant(Instant.ofEpochSecond((int)valMap.get("seconds")).plusNanos((int)valMap.get("nanos")),
                            ZoneId.of("UTC"));
                    val = d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
                }
                
            } else {
                val = fixJsonTimestamps(valMap);
            }
        } else if(val instanceof List && ((List) val).size() > 0 && 
                ((List) val).get(0) instanceof Map) {
            List<Map<String, Object>> outputList = new ArrayList<>();
            for(Map item : (List<Map>)val) {
                outputList.add(fixJsonTimestamps(item));
            }
            val = outputList;
        }
        outMap.put(key, val);
    }
    return outMap;
}

가장 이상적인 솔루션은 아니지만 현재 작업에는 효과가 있습니다. 누군가 다른 타임스탬프 클래스를 사용하도록 권장하는 것을 본 것 같습니다.

builder와 json String을 사용하여 json 문자열을 Proto로 변환할 수 있습니다.

예:

YourProto.Builder protoBuilder = YourProto.newBuilder();
JsonFormat.parser().merge(JsonString, protoBuilder);

알 수 없는 json 필드를 무시하려면

 YourProto.Builder protoBuilder = YourProto.newBuilder();
 JsonFormat.parser()..ignoringUnknownFields().merge(JsonString, protoBuilder);

 

또 다른 방법은 ProtocolBuffer에서 mergeFrom 메서드를 사용하는 것입니다.

예:

YourProto.Builder protoBuilder = YourProto.newBuilder();
protoBuilder.mergeFrom(JsonString.getBytes());

실행되면 protoBuilder의 모든 데이터를 json String에서 가져옵니다.

온라인 서비스: https://json-to-proto.github.io/

이 도구는 JSON을 즉시 Protobuf로 변환합니다.왼쪽에 JSON 구조를 붙여넣으면 오른쪽에 동등한 Protobuf가 생성되어 프로그램에 붙여넣을 수 있습니다.이 스크립트는 몇 가지 가정을 해야 하므로 출력을 다시 확인하십시오.

언급URL : https://stackoverflow.com/questions/38406211/how-to-convert-from-json-to-protobuf

반응형