3

I want to convert my Protobuf object to a JSON object using PHP so that I can send it back to the browser.

My Protobuf is

syntax = "proto3";
package Protobuf.Gen.ProposalTotalModel;
option php_generic_services = true;

message ProposalTotal {

  message Total {
    double static = 1;
    double hourly = 2;
    double monthly = 3;
    double annual = 4;
  }

  message TotalAfterTax {
    double static = 1;
    double hourly = 2;
    double monthly = 3;
    double annual = 4;
  }

  Total total = 1;
  TotalAfterTax total_after_tax = 2;
  bool has_totals = 3;
}

The protobuf generated code from the above file(skipping few other auto-generated files):

<?php
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: proposal_total.proto

namespace Protobuf\Gen\ProposalTotalModel;

use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;

/**
 * Generated from protobuf message <code>Protobuf.Gen.ProposalTotalModel.ProposalTotal</code>
 */
class ProposalTotal extends \Google\Protobuf\Internal\Message
{
    /**
     * Generated from protobuf field <code>.Protobuf.Gen.ProposalTotalModel.ProposalTotal.Total total = 1;</code>
     */
    private $total = null;
    /**
     * Generated from protobuf field <code>.Protobuf.Gen.ProposalTotalModel.ProposalTotal.TotalAfterTax total_after_tax = 2;</code>
     */
    private $total_after_tax = null;
    /**
     * Generated from protobuf field <code>bool has_totals = 3;</code>
     */
    private $has_totals = false;

    /**
     * Constructor.
     *
     * @param array $data {
     *     Optional. Data for populating the Message object.
     *
     *     @type \Protobuf\Gen\ProposalTotalModel\ProposalTotal\Total $total
     *     @type \Protobuf\Gen\ProposalTotalModel\ProposalTotal\TotalAfterTax $total_after_tax
     *     @type bool $has_totals
     * }
     */
    public function __construct($data = NULL) {
        \GPBMetadata\ProposalTotal::initOnce();
        parent::__construct($data);
    }

    /**
     * Generated from protobuf field <code>.Protobuf.Gen.ProposalTotalModel.ProposalTotal.Total total = 1;</code>
     * @return \Protobuf\Gen\ProposalTotalModel\ProposalTotal\Total
     */
    public function getTotal()
    {
        return $this->total;
    }

    /**
     * Generated from protobuf field <code>.Protobuf.Gen.ProposalTotalModel.ProposalTotal.Total total = 1;</code>
     * @param \Protobuf\Gen\ProposalTotalModel\ProposalTotal\Total $var
     * @return $this
     */
    public function setTotal($var)
    {
        GPBUtil::checkMessage($var, \Protobuf\Gen\ProposalTotalModel\ProposalTotal_Total::class);
        $this->total = $var;

        return $this;
    }

    /**
     * Generated from protobuf field <code>.Protobuf.Gen.ProposalTotalModel.ProposalTotal.TotalAfterTax total_after_tax = 2;</code>
     * @return \Protobuf\Gen\ProposalTotalModel\ProposalTotal\TotalAfterTax
     */
    public function getTotalAfterTax()
    {
        return $this->total_after_tax;
    }

    /**
     * Generated from protobuf field <code>.Protobuf.Gen.ProposalTotalModel.ProposalTotal.TotalAfterTax total_after_tax = 2;</code>
     * @param \Protobuf\Gen\ProposalTotalModel\ProposalTotal\TotalAfterTax $var
     * @return $this
     */
    public function setTotalAfterTax($var)
    {
        GPBUtil::checkMessage($var, \Protobuf\Gen\ProposalTotalModel\ProposalTotal_TotalAfterTax::class);
        $this->total_after_tax = $var;

        return $this;
    }

    /**
     * Generated from protobuf field <code>bool has_totals = 3;</code>
     * @return bool
     */
    public function getHasTotals()
    {
        return $this->has_totals;
    }

    /**
     * Generated from protobuf field <code>bool has_totals = 3;</code>
     * @param bool $var
     * @return $this
     */
    public function setHasTotals($var)
    {
        GPBUtil::checkBool($var);
        $this->has_totals = $var;

        return $this;
    }

}

I was able to convert my JSON object to a Protobuf object for storage in Redis on doing a POST request

$total = new \Protobuf\Gen\ProposalTotalModel\ProposalTotal( );
$total->mergeFromJsonString( $body, false );

Then, for a GET request, I want to take this object stored in Redis and send it back to the client. I know that in other languages, we could use JsonFormat.printer().print(obj);. But I could not find similar functionality in PHP to do so. Is it possible to generate JSON automatically or do I have to manually construct the JSON by getting all the getter fields from the Protobuf object?

json_encode is out of scope as the generated Php file properties are private.

srth12
  • 873
  • 9
  • 16

1 Answers1

4

use $total->serializeToJsonString(). I tried it in laravel & it works example code

It is very similar to

JsonFormat.printer().print(myBuiltProtoObject);
Route::get('/rpc', function () {
    // include_once '../protos/Person.php';
    $aBook = new AddressBook();
    $aBook->setPerson([
        (function () {
            $p = new Person();

            $p->setName('Helloname');
            $p->setId(10015);

            $p->setPhone([
                (function () {
                    $pn = new PhoneNumber();
                    $pn->setNumber('6281284842477');
                    $pn->setType(PhoneType::MOBILE);

                    return $pn;
                })(),
                (function () {
                    $pn = new PhoneNumber();
                    $pn->setNumber('62215501728');
                    $pn->setType(PhoneType::WORK);

                    return $pn;
                })(),
            ]);

            return $p;
        })(),
        (function () {
            $p2 = new Person();
            $p2->setName('Masdani');
            $p2->setId(10016);

            return $p2;
        })()
    ]);

    return response()->json(json_decode($aBook->serializeToJsonString()));
});