Attached is a GTest that serializes to JSON, uses the 
google.protobuf.Timestamp type and sets an Any field.
Example of attached:
syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

package movie.pbuf;


// This message is a one-to-one mapping to the Movie Collection in our 
MongoDB
message Movie {
  google.protobuf.Timestamp start_time = 1;
  string movie_name = 2;
  // TODO action flag
  // TODO add more here
}

message CommandControlMsg {
  string message = 1;
  google.protobuf.Any command = 2;
}


Here's a test snippet
/**
 * Serialize a protobuf message to JSON and parse back again.
 */
TEST_F(BasicProtoGtest, SerializeToJsonAndBackAgain) {
  // Movie PBUF message
  Movie startMovie;

  struct timeval tv;
  gettimeofday(&tv, NULL);

  ::google::protobuf::Timestamp* timestamp = new 
::google::protobuf::Timestamp();
  timestamp->set_seconds(tv.tv_sec);
  timestamp->set_nanos(tv.tv_usec * 1000);
  
  startMovie.set_allocated_start_time(timestamp);
  startMovie.set_movie_name("my happy movie");
  
  std::string serialized = startMovie.SerializeAsString();
  std::string json_string;
  
  // Create a TypeResolver used to resolve protobuf message types
  google::protobuf::util::JsonOptions options;
  options.always_print_primitive_fields = true;
  std::unique_ptr<google::protobuf::util::TypeResolver> 
resolver(google::protobuf::util::NewTypeResolverForDescriptorPool(
    "type.googleapis.com", 
google::protobuf::DescriptorPool::generated_pool())); 
  
  // Assert we can find the Movie type in the resolver
  Type type;
  ASSERT_TRUE(resolver->ResolveMessageType(
    "type.googleapis.com/movie.pbuf.Movie", &type).ok());
  
  auto status = google::protobuf::util::BinaryToJsonString(resolver.get(), 
"type.googleapis.com/movie.pbuf.Movie", serialized, &json_string, options);
//   std::cout << "~~~~~~~ bin str\n" << serialized << std::endl;
   std::cout << "*******\n" << json_string << std::endl;
  
  // Turn JSON into serialized protobuf message
  std::string movieBin;
  google::protobuf::util::JsonToBinaryString(resolver.get(), 
"type.googleapis.com/movie.pbuf.Movie", json_string, &movieBin);  
  
  Movie startMovie2;
  startMovie2.ParseFromString(movieBin);
  
  EXPECT_EQ(startMovie.movie_name(), startMovie2.movie_name());
  EXPECT_EQ(startMovie.start_time(), startMovie2.start_time());  
}

Build the project with cmake using standard "out of source" build:
cd project_dir
mkdir build
cd build
cmake ..
make
ctest


This was done on Fedora Core 23



On Monday, June 13, 2016 at 9:47:38 AM UTC-7, Carl wrote:
>
> Greetings:
>
>      As someone who is fairly familiar with PB 2.0, I have used it for 2+ 
> years. I feel comfortable standard C++ API of has_*. set_* and the parsing 
> and serialization APIs.
>
>      But now as I am moving to PB 3.0 I keep hearing of JSON as a possible 
> serialization format. But how?
>
>       Is there an example of how a C++ app can read/write a PB to JSON. I 
> already have a include file (.h) generated via protoc (ver 3) and don't see 
> a published UI.
>
> Thanks
> Carl
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to protobuf+unsubscr...@googlegroups.com.
To post to this group, send email to protobuf@googlegroups.com.
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.
/**
 * 
 */
#include <sys/time.h>
#include <memory>
#include <vector>

#include "gmock/gmock.h"
#include "basic_proto_gtest.h"
#include "movie.pb.h"
#include <google/protobuf/type.pb.h>
#include <google/protobuf/util/json_util.h>

#include <google/protobuf/util/time_util.h>
#include <google/protobuf/timestamp.pb.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/util/type_resolver_util.h>

using google::protobuf::Type;

namespace movie {
namespace pbuf {

  using ::testing::Return;

BasicProtoGtest::BasicProtoGtest() {}
BasicProtoGtest::~BasicProtoGtest() {};
void BasicProtoGtest::SetUp() {};
void BasicProtoGtest::TearDown() {};


/**
 * Serialize a protobuf message to JSON and parse back again.
 */
TEST_F(BasicProtoGtest, SerializeToJsonAndBackAgain) {
  // Movie PBUF message
  Movie startMovie;

  struct timeval tv;
  gettimeofday(&tv, NULL);

  ::google::protobuf::Timestamp* timestamp = new ::google::protobuf::Timestamp();
  timestamp->set_seconds(tv.tv_sec);
  timestamp->set_nanos(tv.tv_usec * 1000);
  
  startMovie.set_allocated_start_time(timestamp);
  startMovie.set_movie_name("my happy movie");
  
  std::string serialized = startMovie.SerializeAsString();
  std::string json_string;
  
  // Create a TypeResolver used to resolve protobuf message types
  google::protobuf::util::JsonOptions options;
  options.always_print_primitive_fields = true;
  std::unique_ptr<google::protobuf::util::TypeResolver> resolver(google::protobuf::util::NewTypeResolverForDescriptorPool(
    "type.googleapis.com", google::protobuf::DescriptorPool::generated_pool())); 
  
  // Assert we can find the Movie type in the resolver
  Type type;
  ASSERT_TRUE(resolver->ResolveMessageType(
    "type.googleapis.com/movie.pbuf.Movie", &type).ok());
  
  auto status = google::protobuf::util::BinaryToJsonString(resolver.get(), "type.googleapis.com/movie.pbuf.Movie", serialized, &json_string, options);
//   std::cout << "~~~~~~~ bin str\n" << serialized << std::endl;
   std::cout << "*******\n" << json_string << std::endl;
  
  // Turn JSON into serialized protobuf message
  std::string movieBin;
  google::protobuf::util::JsonToBinaryString(resolver.get(), "type.googleapis.com/movie.pbuf.Movie", json_string, &movieBin);  
  
  Movie startMovie2;
  startMovie2.ParseFromString(movieBin);
  
  EXPECT_EQ(startMovie.movie_name(), startMovie2.movie_name());
  EXPECT_EQ(startMovie.start_time(), startMovie2.start_time());  
}

/**
 * Put a message in an Any type and verify it works.
 */
TEST_F(BasicProtoGtest, VerifyAnyType) {
  // Storing an arbitrary message type in Any.
  Movie startMovie;
  CommandControlMsg ccMsg;
  ::google::protobuf::Any* cmdAny = ccMsg.mutable_command();
  
  struct timeval tv;
  gettimeofday(&tv, NULL);  
  ::google::protobuf::Timestamp* timestamp = new ::google::protobuf::Timestamp();
  timestamp->set_seconds(tv.tv_sec);
  timestamp->set_nanos(tv.tv_usec * 1000);
  
  startMovie.set_allocated_start_time(timestamp);
  startMovie.set_movie_name("my happy movie title");
  // Pack the StartMovie into the CommandControlMsg.command
  cmdAny->PackFrom(startMovie);


  std::string serialized = ccMsg.SerializeAsString();
  std::string json_string;
  
  // 
  // Create a TypeResolver used to resolve protobuf message types
  google::protobuf::util::JsonOptions options;
  options.always_print_primitive_fields = true;
  std::unique_ptr<google::protobuf::util::TypeResolver> resolver(google::protobuf::util::NewTypeResolverForDescriptorPool(
    "type.googleapis.com", google::protobuf::DescriptorPool::generated_pool())); 
  auto status = google::protobuf::util::BinaryToJsonString(resolver.get(), "type.googleapis.com/movie.pbuf.CommandControlMsg", serialized, &json_string, options);
  // print out CommandControlMsg as JSON string
  std::cout << "*******\n" << json_string << std::endl;
  
  
  // Assert command is Movie type
  ASSERT_TRUE(ccMsg.command().Is<Movie>());
  // Get Movie from Any
  Movie startMovieFromAny;
  ccMsg.command().UnpackTo(&startMovieFromAny);
  EXPECT_EQ(startMovie.movie_name(), startMovieFromAny.movie_name());
  EXPECT_EQ(startMovie.start_time(), startMovieFromAny.start_time());  
}

}
}
#ifndef _BasicProtoGtest_H
#define	_BasicProtoGtest_H

#include "gtest/gtest.h"

namespace movie {
  namespace pbuf {
// The fixture for testing.
class BasicProtoGtest : public ::testing::Test {

protected:

    // You can do set-up work for each test here.
  BasicProtoGtest();

    // You can do clean-up work that doesn't throw exceptions here.
  virtual ~BasicProtoGtest();

    // If the constructor and destructor are not enough for setting up
    // and cleaning up each test, you can define the following methods:

    // Code here will be called immediately after the constructor (right
    // before each test).
    virtual void SetUp();

    // Code here will be called immediately after each test (right
    // before the destructor).
    virtual void TearDown();

};

  }
  
}
#endif	/* _BasicProtoGtest_H */
project(movie C CXX)
cmake_minimum_required(VERSION 3.1)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED on)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../bin)

# Setup Valgrind for cmake -D ExperimentalMemCheck
find_program( MEMORYCHECK_COMMAND REQUIRED valgrind )
set( MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full 
--show-leak-kinds=all" )
set( MEMORYCHECK_SUPPRESSIONS_FILE 
"${PROJECT_SOURCE_DIR}/valgrind_suppress.txt" )

include( CTest )

find_package( Threads )
find_package(Threads REQUIRED) 
find_package(GTest REQUIRED gtest>=1.7.0)

FIND_LIBRARY(GMOCK_LIBRARY gmock /usr/local/lib/libgmock)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(/usr/local/include)


# *************** Movie PBUF Library ********************* 
include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(MOVIE_PROTO_SRCS MOVIE_PROTO_HDRS movie.proto)
add_library(movie_proto STATIC ${MOVIE_PROTO_SRCS} ${MOVIE_PROTO_HDRS})

target_link_libraries(movie_proto ${PROTOBUF_LIBRARIES})

# Specify here the include directories exported
# by this library. Note the CMAKE_CURRENT_BINARY_DIR is the build dir. That's 
because the src and header files are generated in the build dir by protoc
target_include_directories(movie_proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR}  
${CMAKE_CURRENT_SOURCE_DIR})

# ********************************************************

# *************** Libarary with Main that calls   
google::protobuf::ShutdownProtobufLibrary();
#
# gtest_protobuf_main library
#   Use this main for GTtests that use protobuf to ensure protobuf library 
shutdown
#
add_library(gtest_protobuf_main STATIC
  gtestProtobufMain.cpp
)
# ********************************************************

#
# BasicProtoGtest
#
ADD_EXECUTABLE(BasicProtoGtest
  basic_proto_gtest.h
  basic_proto_gtest.cpp)

TARGET_LINK_LIBRARIES(BasicProtoGtest
  gtest_protobuf_main
  ${PROTOBUF_LIBRARIES}
  ${GTEST_LIBRARIES}
  ${GMOCK_LIBRARY}
  ${CMAKE_THREAD_LIBS_INIT}
  movie_proto
)
add_test(NAME BasicProtoGtest
  COMMAND BasicProtoGtest)
#include "gtest/gtest.h"
#include "google/protobuf/message.h"


/**
 * This app is used to run GTests when you're using the protobuf library. It ensures proper shutdown of the protobuf
 * library show Valgrind won't complain about a bunch of memory leaks.
 */
int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int ret = RUN_ALL_TESTS();
  google::protobuf::ShutdownProtobufLibrary();

  return ret;
}

Attachment: movie.proto
Description: Binary data

Reply via email to