2

I have an array of JSON objects that looks like this...

JSONarray = 
[ { name: 'Steven' },
  { name: 'Clark' },
  { name: 'Kensington' } ]

With respect to dialogflow and google assistant I would need to send a webhook response that looks something like this...

"fulfillmentText": JSONarray}),
  "fulfillmentMessages" : [
          {
            "text":
              {"text": [JSONarray]
            }
          }
        ]}

The issue I have is this piece "fulfillmentText": JSONarray. 'fulfillmentText' is the part that Google Assistant reads back and ideally I want to have it read back each of the three names but if I just pass the array it fails. Is there away I can build the JSON that will let this happen?

Prisoner
  • 49,922
  • 7
  • 53
  • 105
SonOfNye
  • 75
  • 8

1 Answers1

2

First, a minor semantic point. That is not a "JSON Array". It is an array of JavaScript Objects. JSON refers to the string representation of those objects (JavaScript Object Notation).

This is important because "fulfillmentText" expects a string. You can turn JavaScript objects into a string by using the JSON.stringify() method, so you'd do something like

const text = JSON.stringify( JSONarray );

However, this probably isn't what you want, since the Assistant would read this out as something like

Open bracket open brace quote name quote colon quote Steven quote close bracket, ...

and so forth.

Instead, you probably should write a function that takes the array and turns it into a string. Simplistically, you could call join() on just the values of the names. Something like this:

const names = JSONarray.map( o => o.name );  // Gets just an array of the names
const namesString = names.join(', ');  // Joins them into a single string, separated by commas
const text = `The names are: ${namesString}`;

This is better, and what would be read out is something like

The names are Steven, Clark, Kensington

But this isn't how people actually read (or listen to) names. We expect it to be something more like

The names are Steven, Clark, and Kensington

This is so common that multivocal includes a template function to do this based on a list of strings. So your template would just be something like:

"The names are: {{Oxford names}}"

If you're not using multivocal, something like this would work:

/**
 * Similar to Array.join(), but using rules for the Oxford comma.
 * @param values The array to return joined values for
 * @param sep1 The normal separator for each element (defaults to ", ")
 * @param sep2 The separator before the final element (defaults to "and ")
 * @returns {*}
 */
function oxford( values, sep1=", ", sep2="and " ){
  if( !Array.isArray( values ) ){
    return values;
  } else if( values.length === 0 ){
    return '';
  } else if( values.length === 1 ){
    return values[0];
  } else if( values.length === 2 ){
    return values[0]+' '+sep2+values[1];
  }

  var ret = '';

  for( var co=0; co<values.length-1; co++ ){
    ret += values[co]+sep1;
  }
  ret += sep2;
  ret += values[values.length-1];

  return ret;
};

const namesString = oxford( names );
const text = `The names are: ${namesString}`;
Prisoner
  • 49,922
  • 7
  • 53
  • 105