Protocol buffer3 and json

前端 未结 2 882
谎友^
谎友^ 2021-02-05 13:43

Protocol buffer v3 claims, that library is json friendly (https://developers.google.com/protocol-buffers/docs/proto3#json), but I cannot find how to achieve get that mapping. Sh

2条回答
  •  野的像风
    2021-02-05 14:06

    I'm using Protobuf 3.3.0, which does have a built-in JSON serializer and parser. You can use 2 functions from google/protobuf/util/json_util.h called MessageToJsonString() and JsonStringToMessage() to make your C++ generated Message objects go to and from JSON respectively.

    Here's a simple test that uses them: test-protobuf.proto:

    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    

    test-protobuf.cpp:

    #include 
    #include 
    
    #include "test-protobuf.pb.h"
    
    int main()
    {
      std::string json_string;
      SearchRequest sr, sr2;
    
      // Populate sr.
      sr.set_query(std::string("Hello!"));
      sr.set_page_number(1);
      sr.set_result_per_page(10);
    
      // Create a json_string from sr.
      google::protobuf::util::JsonPrintOptions options;
      options.add_whitespace = true;
      options.always_print_primitive_fields = true;
      options.preserve_proto_field_names = true;
      MessageToJsonString(sr, &json_string, options);
    
      // Print json_string.
      std::cout << json_string << std::endl;
    
    
      // Parse the json_string into sr2.
      google::protobuf::util::JsonParseOptions options2;
      JsonStringToMessage(json_string, &sr2, options2);
    
      // Print the values of sr2.
      std::cout
        << sr2.query() << ", "
        << sr2.page_number() << ", "
        << sr2.result_per_page() << std::endl
      ;
    
      return 0;
    }
    

    You can compile these files (assuming that you have protobuf, a compiler, and CMake installed) by using the following CMakeLists.txt file (tested on Windows).

    cmake_minimum_required(VERSION 3.8)
    
    project(test-protobuf)
    
    find_package(Protobuf REQUIRED)
    
    # Use static runtime for MSVC
    if(MSVC)
      foreach(flag_var
          CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
          CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
        if(${flag_var} MATCHES "/MD")
          string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
        endif(${flag_var} MATCHES "/MD")
      endforeach(flag_var)
    endif(MSVC)
    
    protobuf_generate_cpp(test-protobuf-sources test-protobuf-headers
      "${CMAKE_CURRENT_LIST_DIR}/test-protobuf.proto"
    )
    
    list(APPEND test-protobuf-sources
      "${CMAKE_CURRENT_LIST_DIR}/test-protobuf.cpp"
    )
    
    add_executable(test-protobuf ${test-protobuf-sources} ${test-protobuf-headers})
    target_include_directories(test-protobuf
      PUBLIC
        ${PROTOBUF_INCLUDE_DIRS}
        ${CMAKE_CURRENT_BINARY_DIR}
    )
    target_link_libraries(test-protobuf
      ${PROTOBUF_LIBRARIES}
    )
    

    Assuming that CMakeLists.txt, test-protobuf.proto, and test-protobuf.cpp are in the same directory, here are the commands to compile and run them on Windows with Visual Studio 15 2017 and 64-bit protobuf libraries.

    mkdir build
    cd build
    cmake -G "Visual Studio 15 2017 Win64" ..
    cmake --build . --config Release
    Release/test-protobuf
    

    You should see the following output:

    {
     "query": "Hello!",
     "page_number": 1,
     "result_per_page": 10
    }
    
    Hello!, 1, 10
    

提交回复
热议问题