[json encoder] passes almost all conformance tests.
diff --git a/upb/json_encode.c b/upb/json_encode.c
index 46d6c33..8086f1c 100644
--- a/upb/json_encode.c
+++ b/upb/json_encode.c
@@ -245,6 +245,8 @@
     jsonenc_putstr(e, "\"Infinity\"");
   } else if (val == -UPB_INFINITY) {
     jsonenc_putstr(e, "\"-Infinity\"");
+  } else if (val != val) {
+    jsonenc_putstr(e, "\"NaN\"");
   } else {
     jsonenc_printf(e, fmt, val);
   }
@@ -257,6 +259,27 @@
   jsonenc_scalar(e, val, val_f);
 }
 
+const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) {
+  /* Find last '/', if any. */
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+
+  if (!e->ext_pool || type_url.size == 0) return NULL;
+
+  while (true) {
+    if (--ptr == type_url.data) {
+      /* Type URL must contain at least one '/', with host before. */
+      return NULL;
+    }
+    if (*ptr == '/') {
+      ptr++;
+      break;
+    }
+  }
+
+  return upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr);
+}
+
 static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
   const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
   const upb_fielddef *value_f = upb_msgdef_itof(m, 1);
@@ -286,14 +309,52 @@
   jsonenc_putstr(e, "}");
 }
 
-static void jsonenc_putsep(jsonenc *e, bool *first) {
+static void jsonenc_putsep(jsonenc *e, const char *str, bool *first) {
   if (*first) {
     *first = false;
   } else {
-    jsonenc_putstr(e, ", ");
+    jsonenc_putstr(e, str);
   }
 }
 
+static void jsonenc_fieldpath(jsonenc *e, upb_strview path) {
+  const char *ptr = path.data;
+  const char *end = ptr + path.size;
+
+  while (ptr < end) {
+    char ch = *ptr;
+    if (ch >= 'A' && ch <= 'Z') {
+      jsonenc_err(e, "Field mask element may not have upper-case letter.");
+    } else if (ch == '_') {
+      if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') {
+        jsonenc_err(e, "Underscore must be followed by a lowercase letter.");
+      }
+    } else {
+      jsonenc_putbytes(e, &ch, 1);
+    }
+    ptr++;
+  }
+}
+
+static void jsonenc_fieldmask(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  const upb_array *paths = upb_msg_get(msg, paths_f).array_val;
+  bool first = true;
+  size_t i, n = 0;
+
+  if (paths) n = upb_array_size(paths);
+
+  jsonenc_putstr(e, "\"");
+
+  for (i = 0; i < n; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_fieldpath(e, upb_array_get(paths, i).str_val);
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
 static void jsonenc_struct(jsonenc *e, const upb_msg *msg,
                            const upb_msgdef *m) {
   const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
@@ -309,7 +370,7 @@
     upb_msgval key = upb_mapiter_key(fields, iter);
     upb_msgval val = upb_mapiter_value(fields, iter);
 
-    jsonenc_putsep(e, &first);
+    jsonenc_putsep(e, ", ", &first);
     jsonenc_string(e, key.str_val);
     jsonenc_putstr(e, ": ");
     jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f));
@@ -332,7 +393,7 @@
   for (i = 0; i < size; i++) {
     upb_msgval elem = upb_array_get(values, i);
 
-    jsonenc_putsep(e, &first);
+    jsonenc_putsep(e, ", ", &first);
     jsonenc_value(e, elem.msg_val, values_m);
   }
 
@@ -382,6 +443,8 @@
       jsonenc_any(e, msg, m);
       break;
     case UPB_WELLKNOWN_FIELDMASK:
+      jsonenc_fieldmask(e, msg, m);
+      break;
     case UPB_WELLKNOWN_DURATION:
       jsonenc_duration(e, msg, m);
       break;
@@ -486,7 +549,7 @@
   jsonenc_putstr(e, "[");
 
   for (i = 0; i < size; i++) {
-    jsonenc_putsep(e, &first);
+    jsonenc_putsep(e, ", ", &first);
     jsonenc_scalar(e, upb_array_get(arr, i), f);
   }
 
@@ -503,7 +566,7 @@
   jsonenc_putstr(e, "{");
 
   while (upb_mapiter_next(map, &iter)) {
-    jsonenc_putsep(e, &first);
+    jsonenc_putsep(e, ", ", &first);
     jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f);
     jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f);
   }
@@ -524,7 +587,7 @@
     name = buf;
   }
 
-  jsonenc_putsep(e, first);
+  jsonenc_putsep(e, ", ", first);
   jsonenc_printf(e, "\"%s\": ", name);
 
   if (upb_fielddef_ismap(f)) {
@@ -573,9 +636,9 @@
   return ret;
 }
 
-size_t upb_jsonencode(const upb_msg *msg, const upb_msgdef *m,
-                      const upb_symtab *ext_pool, int options, char *buf,
-                      size_t size, upb_status *status) {
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status) {
   jsonenc e;
 
   e.buf = buf;