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.
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);
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)
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With