code: @Override
      public Value toProto(Object val) {
          Value.Builder builder = Value.newBuilder();
  
          if (val == null) {
              builder.setNullValue(NullValue.NULL_VALUE);
          } else if (val instanceof Boolean) {
              builder.setBoolValue((Boolean) val);
          } else if (val instanceof Double) {
              builder.setNumberValue((Double) val);
          } else if (val instanceof String) {
              builder.setStringValue((String) val);
          } else if (val instanceof Map) {
              Map<String, Object> map = (Map<String, Object>) val;
              Struct.Builder struct = Struct.newBuilder();
              for (Map.Entry<String, Object> pair : map.entrySet()) {
                  struct.putFields(pair.getKey(), toProto(pair.getValue()));
              }
              builder.setStructValue(struct.build());
          } else if (val instanceof List) {
              ListValue.Builder list = ListValue.newBuilder();
              for (Object obj : (List<Object>)val) {
                  list.addValues(toProto(obj));
              }
              builder.setListValue(list.build());
          } else {
              throw new ClassCastException("cannot map to Value type: "+val);
          }
          return builder.build();
      }
docs: Convert an {@link Object} instance into its equivalent {@link Value}
  ProtoBuf object.
  
  The {@link Value} ProtoBuf message is a variant type that can define any
  value representable as a native JSON type. Consequently, this method expects
  the given {@link Object} instance to be a Java object instance of JSON-native
  value, namely: null, {@link Boolean}, {@link Double}, {@link String},
  {@link Map}, {@link List}.
  
  Any other values will cause an exception to be thrown.
  See {@link ProtoMapper#fromProto(Value)} for the reverse mapping.
  
  @param val a Java object that can be represented natively in JSON
  @return an instance of a {@link Value} ProtoBuf message