diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 9dca682..182837b 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -419,6 +419,7 @@ DefineTSDictionary(List *names, List *parameters)
 	NameData	dname;
 	Oid			templId = InvalidOid;
 	List	   *dictoptions = NIL;
+	Datum		dictoptions_s;
 	Oid			dictOid;
 	Oid			namespaceoid;
 	AclResult	aclresult;
@@ -453,6 +454,20 @@ DefineTSDictionary(List *names, List *parameters)
 	}
 
 	/*
+	 * Immediately serialize the parameters, and then deserialize so that what
+	 * we pass to validation is the same representation that will be seen at
+	 * runtime.  This is a kluge to cope with the fact that the serialization
+	 * logic fails to reproduce the node structure exactly.
+	 */
+	if (dictoptions)
+	{
+		dictoptions_s = PointerGetDatum(serialize_deflist(dictoptions));
+		dictoptions = deserialize_deflist(dictoptions_s);
+	}
+	else
+		dictoptions_s = (Datum) 0;
+
+	/*
 	 * Validation
 	 */
 	if (!OidIsValid(templId))
@@ -480,8 +495,7 @@ DefineTSDictionary(List *names, List *parameters)
 	values[Anum_pg_ts_dict_dictowner - 1] = ObjectIdGetDatum(GetUserId());
 	values[Anum_pg_ts_dict_dicttemplate - 1] = ObjectIdGetDatum(templId);
 	if (dictoptions)
-		values[Anum_pg_ts_dict_dictinitoption - 1] =
-			PointerGetDatum(serialize_deflist(dictoptions));
+		values[Anum_pg_ts_dict_dictinitoption - 1] = dictoptions_s;
 	else
 		nulls[Anum_pg_ts_dict_dictinitoption - 1] = true;
 
@@ -537,6 +551,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
 	Oid			dictId;
 	ListCell   *pl;
 	List	   *dictoptions;
+	Datum		dictoptions_s;
 	Datum		opt;
 	bool		isnull;
 	Datum		repl_val[Natts_pg_ts_dict];
@@ -595,6 +610,20 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
 	}
 
 	/*
+	 * Immediately serialize the parameters, and then deserialize so that what
+	 * we pass to validation is the same representation that will be seen at
+	 * runtime.  This is a kluge to cope with the fact that the serialization
+	 * logic fails to reproduce the node structure exactly.
+	 */
+	if (dictoptions)
+	{
+		dictoptions_s = PointerGetDatum(serialize_deflist(dictoptions));
+		dictoptions = deserialize_deflist(dictoptions_s);
+	}
+	else
+		dictoptions_s = (Datum) 0;
+
+	/*
 	 * Validate
 	 */
 	verify_dictoptions(((Form_pg_ts_dict) GETSTRUCT(tup))->dicttemplate,
@@ -608,8 +637,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
 	memset(repl_repl, false, sizeof(repl_repl));
 
 	if (dictoptions)
-		repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
-			PointerGetDatum(serialize_deflist(dictoptions));
+		repl_val[Anum_pg_ts_dict_dictinitoption - 1] = dictoptions_s;
 	else
 		repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true;
 	repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true;
@@ -1522,6 +1550,9 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
  *
  * Note that we assume that only the textual representation of an option's
  * value is interesting --- hence, non-string DefElems get forced to strings.
+ * This is, in fact, wrong.  For example, defGetBoolean accepts integers 0
+ * and 1 but not the string equivalents of those.  Pending making this smarter,
+ * callers must avoid assuming that serialize/deserialize is an identity.
  */
 text *
 serialize_deflist(List *deflist)
