json_codec library

Descriptor-driven Proto3 JSON marshaling and unmarshaling.

Converts between Dart Map<String, Object?> message representations and Proto3 JSON format, using the same field descriptor lists as the binary marshal.dart / unmarshal.dart codecs.

Field descriptor format (same as binary marshal/unmarshal):

{
  'name'     : String,       // snake_case field name
  'number'   : int,          // protobuf field number
  'type'     : String,       // protobuf type: 'TYPE_INT32', 'TYPE_STRING', etc.
  'label'    : String?,      // 'LABEL_REPEATED' for repeated fields
  'typeName' : String?,      // fully-qualified enum/message type name
  'mapEntry' : bool?,        // true if this is a map<K,V> field
  'keyType'  : String?,      // map key type
  'valueType': String?,      // map value type
  'messageDescriptor': List<Map<String, Object?>>?,  // sub-message descriptor
  'enumValues': Map<int, String>?,  // enum ordinal -> name mapping
}

Proto3 JSON rules implemented:

  • Field names: snake_case -> lowerCamelCase in output; accept both on input.
  • int64/uint64: encoded as JSON strings (too large for JS Number).
  • bytes: encoded as base64 strings.
  • float/double: NaN -> "NaN", Infinity -> "Infinity", -Infinity -> "-Infinity".
  • enum: encoded as string name (first enum value name for ordinal 0).
  • bool: true/false.
  • message: nested JSON object.
  • repeated: JSON array.
  • map: JSON object (keys always strings in JSON).
  • Default values are omitted from output.

References:

Properties

anyTypeResolver ↔ List<Map<String, Object?>>? Function(String typeName)?
The library-global Any resolver, set by the host (e.g. conformance.dart) to enable Any JSON. It is the fallback used when a JSON (de)serialization is started without a per-call resolver — preserving full backward compatibility for callers that set this once and never thread a resolver per call.
getter/setter pair

Functions

ensureDefaults(Map<String, Object?> message, List<Map<String, Object?>> descriptor) → Map<String, Object?>
Returns a copy of message with missing fields filled in with proto3 default values according to descriptor.
fieldFromJson(Object? jsonValue, String type, {String? typeName, Map<int, String>? enumValues, Map<String, int>? enumNames, List<Map<String, Object?>>? messageDescriptor, Map<String, String>? features, AnyTypeResolver? resolver}) → Object?
Converts a Proto3 JSON value back to its protobuf field representation.
fieldToJson(Object? value, String type, {String? typeName, Map<int, String>? enumValues, List<Map<String, Object?>>? messageDescriptor, Map<String, String>? features, AnyTypeResolver? resolver}) → Object?
Converts a single protobuf field value to its Proto3 JSON representation.
isDefaultValue(Object? value, String type) → bool
Returns true if value is the proto3 default for the given field type.
isWellKnownJsonType(String typeName) → bool
Whether typeName is a well-known type with a dedicated proto3-JSON form. (google.protobuf.Any is excluded — it requires a type registry.)
marshalJson(Map<String, Object?> message, List<Map<String, Object?>> descriptor) → String
Marshals a message to a Proto3 JSON string.
messageFromJson(Object? json, List<Map<String, Object?>> descriptor, {List<Map<String, Object?>>? anyTypeResolver(String typeName)?}) → Map<String, Object?>
Converts a proto3-JSON value json (a decoded Map/List/scalar, NOT a serialized string) into a decoded message map (snake_case proto field names).
messageToJson(Map<String, Object?> message, List<Map<String, Object?>> descriptor, {List<Map<String, Object?>>? anyTypeResolver(String typeName)?}) → Object?
Converts a decoded message message (snake_case proto field names) to its proto3-JSON value — a JSON-compatible Map<String, Object?> (camelCase keys, defaults omitted), NOT a serialized string.
setAnyTypeResolver(List<Map<String, Object?>>? resolver(String typeName)?) → void
Installs the library-global anyTypeResolver hook (used to resolve the type embedded in a google.protobuf.Any during JSON conversion when no per-call resolver is supplied). Kept for backward compatibility — conformance.dart sets it once at startup.
toCamelCase(String snakeCase) → String
Converts a snake_case field name to lowerCamelCase.
toSnakeCase(String camelCase) → String
Converts a lowerCamelCase name to snake_case.
unmarshalJson(String jsonString, List<Map<String, Object?>> descriptor) → Map<String, Object?>
Unmarshals a Proto3 JSON string into a message map.
wktFromJson(String typeName, Object? json, Map<String, String>? features, [AnyTypeResolver? resolver]) → Object?
Converts proto3-JSON json into a decoded WKT message map (snake_case). resolver is the per-call Any resolver (unused by the structural WKTs, threaded only for signature uniformity).
wktToJson(String typeName, Object? value, Map<String, String>? features, [AnyTypeResolver? resolver]) → Object?
Converts a decoded WKT message value (snake_case proto field names) to its proto3-JSON representation. resolver is the per-call Any resolver (unused by the structural WKTs, threaded only for signature uniformity).

Typedefs

AnyTypeResolver = List<Map<String, Object?>>? Function(String typeName)
A function resolving a message type name (stripped FQN, e.g. google.protobuf.Duration) to its field descriptor list.