How to deserialize custom payload response in Dialogflow v2?
Asked Answered
A

5

8

I'm developing my own chatbot for messenger with Dialogflow v2 and the Node.js client SDK. But I've a problem with custom payloads. When I use the console provided by Dialogflow, I have a response which looks like this :

{ "payload": { "facebook": { "attachment": { "payload": { ...

But, when I get the response from my JS server, the custom payload has been serialized. Here is the object I receive :

{ facebook: { structValue: { fields: [Object] }, kind: 'structValue' } }

Is it possible to deserialize this object in order to get the same custom payload structure that I've provided in Dialogflow ?

Thank you in advance.

Aguish answered 1/3, 2018 at 9:5 Comment(1)
Did you find a solution to this issue?Agnesagnese
T
4

this is built using Struct protocols

In order to convert that you would need to use google proto buffer i.e google.protobuf I used the below code to do this.

import google.protobuf  as pf
pf.json_format.MessageToJson(response.query_result.fulfillment_messages[1].payload, including_default_value_fields=False)
Theologue answered 30/4, 2018 at 7:33 Comment(0)
P
5

Edit: Apparently Dialogflow released their own solution with the samples for the Node.js SDK: dialogflow-nodejs-client-v2/samples/structjson.js

Alternatively to the solution of Vikas Jain you could write your own (recursive) conversion function.

Something like:

processCustomPayloadMessage(object) {
  let outputMessage = Array.isArray(object) ? [] : {};
  Object.entries(object).forEach(([key, value]) => {
    if (value.kind == 'structValue') {
      outputMessage[key] = this.processCustomPayloadMessage(value.structValue.fields);
    } else if (value.kind == 'listValue') {
      outputMessage[key] = this.processCustomPayloadMessage(value.listValue.values);
    } else if (value.kind == 'stringValue') {
      outputMessage[key] = value.stringValue;
    } else if (value.kind == 'boolValue') {
      outputMessage[key] = value.boolValue;
    } else {
      outputMessage[key] = value;
    }
  });
  return outputMessage;
}

// call this method with your response message
this.processCustomPayloadMessage(message.payload.fields);
Physical answered 25/6, 2018 at 13:44 Comment(0)
T
4

this is built using Struct protocols

In order to convert that you would need to use google proto buffer i.e google.protobuf I used the below code to do this.

import google.protobuf  as pf
pf.json_format.MessageToJson(response.query_result.fulfillment_messages[1].payload, including_default_value_fields=False)
Theologue answered 30/4, 2018 at 7:33 Comment(0)
F
1

Had same issue, and it's very awful & painful this boring these added k,v that we receive as webhooks in our server, it's because of the structJson I use NodeJS and here is a solution I came to:

const JSON_SIMPLE_VALUE_KINDS = new Set([
  'numberValue',
  'stringValue',
  'boolValue',
]);


function valueProtoToJson(proto) {
  if (!proto || !proto.kind) {
    return null;
  }

  if (JSON_SIMPLE_VALUE_KINDS.has(proto.kind)) {
    return proto[proto.kind];
  } else if (proto.kind === 'nullValue') {
    return null;
  } else if (proto.kind === 'listValue') {
    if (!proto.listValue || !proto.listValue.values) {
      console.warn('Invalid JSON list value proto: ', JSON.stringify(proto));
    }
    return proto.listValue.values.map(valueProtoToJson);
  } else if (proto.kind === 'structValue') {
    return structProtoToJson(proto.structValue);
  } else {
    console.warn('Unsupported JSON value proto kind: ', proto.kind);
    return null;
  }
}


function structProtoToJson(proto) {
  if (!proto || !proto.fields) {
    return {};
  }
  const json = {};
  for (const k in proto.fields) {
    json[k] = valueProtoToJson(proto.fields[k]);
  }
  return json;
}

Once added, you apply this function to your result : 

var correctJSON = valueProtoToJson(Response_dialogflow.fulfillmentMessages[0].payload.fields.facebook)

You simply apply the valueProtoToJson function to the dsired element from Dialogflow response where the payload is : Response_dialogflow.fulfillmentMessages[0]... or 1...

Farceuse answered 15/11, 2018 at 22:20 Comment(0)
D
1

You can now use pb-util for converting from protobuf to JavaScript objects in node. According to this comment on nodejs-dialogflow, this is a temporary solution until this is included in the client library.

Duke answered 29/3, 2019 at 11:11 Comment(0)
B
0

How i decode dialogflow

Format of the response from my API to the (dialogflow webhook fulfillment request)

const response = {
"status":200,
"messages":[{},{} ...]
}

How i read the response from My API to send chat bot or to do something..

var express = require('express');
var {value} = require('pb-util');
var router = express.Router();

...

const status = value.decode(data[0].queryResult.webhookPayload.fields.status);
const messages = value.decode(data[0].queryResult.webhookPayload.fields.messages);

pb-util convert my status and messages into normal JSON object

Barone answered 5/4, 2020 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.