Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deserialize custom payload response in Dialogflow v2?

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.

like image 429
MrOnigiri Avatar asked Mar 01 '18 09:03

MrOnigiri


3 Answers

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);
like image 149
JDK Avatar answered Oct 10 '22 05:10

JDK


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)
like image 3
Vikas Jain Avatar answered Oct 10 '22 05:10

Vikas Jain


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...

like image 1
otymix Avatar answered Oct 10 '22 05:10

otymix