DataBinder class

Copies input values, usually strings from a form or a query, onto the properties of an @Introspected object, then validates it, collecting every problem in one bindingResult.

Use it when the input is a flat map of strings rather than JSON: form fields, query parameters, a CSV row. Each value is converted to the property's type; text that cannot be converted becomes a typeMismatch field error that keeps what was typed, instead of an exception. Rules such as requiredFields and disallowedFields protect the object from missing or unexpected input (a client must not set id or admin).

The web starter does not use it: JSON bodies are read by the ObjectMapper and checked with @Valid(). Spring Boot uses it to validate @ConfigurationProperties classes.

// A signup form: only known fields, `email` required, `id` never set
// by the client.
final form = SignupForm();
final binder = DataBinder(form, objectName: 'signup')
  ..requiredFields = ['email']
  ..disallowedFields = ['id']
  ..validators.add(BeanValidator())
  ..bind({'name': 'Ada', 'age': '36', 'address.city': 'Oslo'})
  ..validate();
if (binder.bindingResult.hasErrors) {
  log.warning(binder.bindingResult.fieldErrors());
}
// {signup: form, BindingResult.signup: ...}; throws on errors.
final model = binder.close();

An immutable class (final fields, no setters) cannot be bound onto. Create it from the values with construct instead: constructor binding, Spring 6.1. It goes through the constructor the generator describes for @Introspected classes, the one ObjectMapper uses:

// Start without a target; construct creates it.
final binder =
    DataBinder(null, objectName: 'book', introspector: introspector)
  ..targetType = Book
  ..construct(MapValueResolver({'isbn': '978-0', 'title': 'Dune'}));
final book = binder.target as Book?; // null when a value was invalid

Spring (Java):

DataBinder binder = new DataBinder(form, "signup");
binder.setRequiredFields("email");
binder.setDisallowedFields("id");
binder.addValidators(validator);
MutablePropertyValues values = new MutablePropertyValues();
values.add("name", "Ada");
values.add("age", "36");
values.add("address.city", "Oslo");
binder.bind(values);
binder.validate();
BindingResult result = binder.getBindingResult();
Map<?, ?> model = binder.close(); // throws BindException on errors

DataBinder books = new DataBinder(null, "book");
books.setTargetType(ResolvableType.forClass(Book.class));
books.construct(valueResolver);

Constructors

DataBinder(Object? target, {String objectName = defaultObjectName, BeanIntrospector? introspector, ConversionService? conversionService, MessageCodesResolver messageCodesResolver = const DefaultMessageCodesResolver()})
A binder for target, or for an object construct creates when target is null; objectName names it in error codes and the model.

Properties

allowedFields ↔ List<String>?
The fields that may be bound, as patterns with * wildcards (address.*); input for other fields is skipped. null or empty allows every field, like Spring's setAllowedFields() with no patterns.
getter/setter pair
autoGrowCollectionLimit ↔ int
The highest list index plus one that binding may create, 256 by default (Spring's DEFAULT_AUTO_GROW_COLLECTION_LIMIT), so input such as items[999999] cannot make the binder allocate a huge list.
getter/setter pair
autoGrowNestedPaths ↔ bool
Whether binding address.city or items[2].sku creates a null nested object, list or map, and missing list elements, on the way; true by default.
getter/setter pair
bindingResult → BeanPropertyBindingResult
The errors of binding and validation, with the target; created on first use for the current target. Read it after bind and validate, or let close throw when it has errors.
no setter
conversionService → ConversionService
Converts input values, usually strings, to the property types.
final
disallowedFields ↔ List<String>
Fields that are never bound, as patterns with * wildcards, such as id or *.admin; they win over allowedFields. Matching ignores case and also catches the bracket form of a dotted path (roles[admin] for roles.admin), as Spring does since CVE-2022-22968. Empty by default.
getter/setter pair
hashCode → int
The hash code for this object.
no setterinherited
ignoreInvalidFields ↔ bool
Whether input for a path that cannot be reached, such as address.city while address is null and cannot be created, is skipped; false by default, and bind throws for it.
getter/setter pair
ignoreUnknownFields ↔ bool
Whether input for a field the target does not have (or a malformed path such as items[) is skipped; true by default. When false, bind throws for it.
getter/setter pair
introspector → BeanIntrospector
Describes the properties and constructors of the target's class and of nested classes.
final
messageCodesResolver → MessageCodesResolver
Builds the message codes of binding and validation errors.
final
objectName → String
The name of the target in error codes (NotBlank.signup.name) and in the model.
final
requiredFields ↔ List<String>
Fields the input must contain with a non-blank value; a missing one gets a required field error. Empty by default. A field that is also disallowed counts as missing.
getter/setter pair
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
suppressedFields → List<String>
The input fields bind skipped because allowedFields or disallowedFields rejected them, over all bind calls; useful to log tampering attempts. Spring's BindingResult.getSuppressedFields().
no setter
target → Object?
The object values are bound onto; null until construct creates it, and still null when that failed.
no setter
targetType ↔ Type?
The class construct creates; it must be @Introspected. Set it before calling construct. Spring's setTargetType.
getter/setter pair
validators → List<Validator>
The validators validate runs, in order; usually the application's BeanValidator and, for rules in code, your own Validators. Empty by default, so nothing is checked until you add one.
final

Methods

bind(Map<String, Object?> values) → void
Sets the target's properties from values, whose keys are property paths (name, address.city, items[0].sku); problems become field errors in bindingResult instead of exceptions.
close() → Map<String, Object?>
Ends binding: throws a BindException when bindingResult has errors, else returns the model map.
construct(ValueResolver valueResolver) → void
Creates the target, an instance of targetType, by calling its constructor with values from valueResolver: constructor binding, for classes with final fields. Spring's DataBinder.construct.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited
validate({List<Type> groups = const []}) → void
Runs each of validators that supports the target, adding the errors to bindingResult; does nothing when there is no target.

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Methods

canonicalPropertyName(String name) → String
name with quotes and surrounding blanks removed from map keys and indexes: map['key'], map["key"] and map[ key ] all become map[key].
simpleMatch(String pattern, String text) → bool
Whether text matches pattern, where * stands for any text (dots included) and everything else matches itself; the matching of allowedFields and disallowedFields. Case-sensitive. Spring's PatternMatchUtils.simpleMatch.

Constants

defaultObjectName → const String
The object name when none is given, target (Spring's DataBinder.DEFAULT_OBJECT_NAME).