diff --git a/README.md b/README.md
index 519d15f6126e43583a27d05b0e777b8feaf9fbf6..c129e94afbe18c2c8ba172848d73a8b89bec7bf3 100644
--- a/README.md
+++ b/README.md
@@ -50,11 +50,11 @@ interface SettingsTab {
 	/**
 	 * Use to set settings from database or defaults.
 	 *
-	 * @param array|ContainerInterface $data Data to render.
+	 * @param ContainerInterface $data Data to render.
 	 *
 	 * @return void
 	 */
-	public function set_data( $data );
+	public function set_data( ContainerInterface $data );
 
 	/**
 	 * Use to handle request data from POST.
@@ -102,11 +102,11 @@ abstract class FieldSettingsTab implements SettingsTab {
 		return $this->get_form()->render_form( $renderer );
 	}
 
-	public function set_data( $data ) {
+	public function set_data( ContainerInterface $data ) {
 		$this->get_form()->set_data( $data );
 	}
 
-	public function handle_request( $request ) {
+	public function handle_request( array $request ) {
 		$this->get_form()->handle_request( $request );
 	}
 
diff --git a/changelog.txt b/changelog.txt
index 10aef4ca0341dbc0807abb45731357d7bb41b917..0fba0c89e9be44c361a333de16592a94a70b686c 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,11 +1,21 @@
 # Changelog
 
-## [3.0.0] - 2021-09-08
+## [3.0.0]
 ### Added
 - Added strong typing to all of the interfaces
 - Added fields sorting by priority field
-###
+- Normalized string escaping in all template files
+- Added InputEmailField and EmailSerializer classes
+### Changed
+- All getters and setter in BasicField are now declared final
+- FormWithFields accepts only ContainerInterface in ::set_data() method. Prepare data before passing it
+### Removed
 - Removed deprecated classes
+- Removed NoSerialize class
+
+## [2.4.7] - 2021-09-20
+### Fixed
+- Add missing escaping functions in templates
 
 ## [2.4.6] - 2021-08-23
 ### Fixed
diff --git a/src/Field.php b/src/Field.php
index 311d8eb2474614314d16e3d948fad8e74e86b427..08329e7f0a4166ed8d3551075b60117770dae779 100644
--- a/src/Field.php
+++ b/src/Field.php
@@ -91,5 +91,7 @@ interface Field {
 
 	public function get_serializer(): Serializer;
 
+	public function has_serializer(): bool;
+
 	public function get_priority(): int;
 }
diff --git a/src/Field/BasicField.php b/src/Field/BasicField.php
index 2855357bf077cc810390d3246ed5fb02bf37220d..4c1dc0cf40c58b7eb0291921b66f1260f5c2b9f7 100644
--- a/src/Field/BasicField.php
+++ b/src/Field/BasicField.php
@@ -6,7 +6,6 @@ use WPDesk\Forms\Field;
 use WPDesk\Forms\Sanitizer;
 use WPDesk\Forms\Sanitizer\NoSanitize;
 use WPDesk\Forms\Serializer;
-use WPDesk\Forms\Serializer\NoSerialize;
 use WPDesk\Forms\Validator;
 use WPDesk\Forms\Validator\ChainValidator;
 use WPDesk\Forms\Validator\RequiredValidator;
@@ -22,7 +21,7 @@ abstract class BasicField implements Field {
 
 	const DEFAULT_PRIORITY = 10;
 
-	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>, serializer: ?Serializer} */
+	/** @var array{default_value: string, possible_values?: string[], sublabel?: string, priority: int, label: string, description: string, description_tip: string, data: array<string|int>} */
 	protected $meta = [
 		'priority'          => self::DEFAULT_PRIORITY,
 		'default_value'     => '',
@@ -30,9 +29,41 @@ abstract class BasicField implements Field {
 		'description'       => '',
 		'description_tip'   => '',
 		'data'              => [],
-		'serializer'        => null,
 	];
 
+	public function should_override_form_template(): bool {
+		return false;
+	}
+
+	public function get_type(): string {
+		return 'text';
+	}
+
+	public function get_validator(): Validator {
+		$chain = new ChainValidator();
+		if ( $this->is_required() ) {
+			$chain->attach( new RequiredValidator() );
+		}
+
+		return $chain;
+	}
+
+	public function get_sanitizer(): Sanitizer {
+		return new NoSanitize();
+	}
+
+	public function has_serializer(): bool {
+		return false;
+	}
+
+	public function get_serializer(): Serializer {
+		throw new \BadMethodCallException('You must define your serializer in a child class.');
+	}
+
+	final public function get_name(): string {
+		return $this->attributes['name'];
+	}
+
 	final public function get_label(): string {
 		return $this->meta['label'];
 	}
@@ -51,11 +82,6 @@ abstract class BasicField implements Field {
 		return ! empty( $this->meta['description_tip'] );
 	}
 
-	/** Override method if you need. */
-	public function should_override_form_template(): bool {
-		return false;
-	}
-
 	final public function get_description(): string {
 		return $this->meta['description'];
 	}
@@ -80,10 +106,6 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function get_type(): string {
-		return 'text';
-	}
-
 	final public function set_placeholder( string $value ): Field {
 		$this->attributes['placeholder'] = $value;
 
@@ -132,9 +154,6 @@ abstract class BasicField implements Field {
 		return $this->attributes['id'] ?? sanitize_title( $this->get_name() );
 	}
 
-	public function get_name(): string {
-		return $this->attributes['name'];
-	}
 
 	final public function is_multiple(): bool {
 		return $this->attributes['multiple'];
@@ -211,37 +230,10 @@ abstract class BasicField implements Field {
 		return $this;
 	}
 
-	public function get_validator(): Validator {
-		$chain = new ChainValidator();
-		if ( $this->is_required() ) {
-			$chain->attach( new RequiredValidator() );
-		}
-
-		return $chain;
-	}
-
 	final public function is_required(): bool {
 		return $this->attributes['required'];
 	}
 
-	public function get_sanitizer(): Sanitizer {
-		return new NoSanitize();
-	}
-
-	final public function get_serializer(): Serializer {
-		if ( ! empty( $this->meta['serializer'] ) && $this->meta['serializer'] instanceof Serializer ) {
-			return $this->meta['serializer'];
-		}
-
-		return new NoSerialize();
-	}
-
-	public function set_serializer( Serializer $serializer ): Field {
-		$this->meta['serializer'] = $serializer;
-
-		return $this;
-	}
-
 	final public function get_priority(): int {
 		return $this->meta['priority'];
 	}
diff --git a/src/Field/NoValueField.php b/src/Field/NoValueField.php
index 90bbecb1d4c622e128c3b95c8d7a934ea2e6598d..53091700da201919178d7b2317dc7e222df105e2 100644
--- a/src/Field/NoValueField.php
+++ b/src/Field/NoValueField.php
@@ -8,7 +8,7 @@ namespace WPDesk\Forms\Field;
  * @package WPDesk\Forms
  */
 abstract class NoValueField extends BasicField {
-	public function get_name(): string {
-		return '';
+	public function __construct() {
+		$this->set_name( '' );
 	}
 }
diff --git a/src/Field/ProductSelect.php b/src/Field/ProductSelect.php
index 2a10e467a6392525b113efa0bd42202be852755b..8d8b5e63620d46d216ce67cede2f1477f02809b4 100644
--- a/src/Field/ProductSelect.php
+++ b/src/Field/ProductSelect.php
@@ -2,11 +2,22 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Serializer\ProductSelectSerializer;
+use WPDesk\Forms\Serializer;
+
 class ProductSelect extends SelectField {
 	public function __construct() {
 		$this->set_multiple();
 	}
 
+	public function has_serializer(): bool {
+		return true;
+	}
+
+	public function get_serializer(): Serializer {
+		return new ProductSelectSerializer();
+	}
+
 	public function get_template_name(): string {
 		return 'product-select';
 	}
diff --git a/src/Field/TimepickerField.php b/src/Field/TimepickerField.php
index 84682545bd7be8f4dfcb00cb3c78f5eed86762e0..c7c1a5d12ad2c222720f2ce62392151c71fe5590 100644
--- a/src/Field/TimepickerField.php
+++ b/src/Field/TimepickerField.php
@@ -2,7 +2,18 @@
 
 namespace WPDesk\Forms\Field;
 
+use WPDesk\Forms\Serializer;
+use WPDesk\Forms\Serializer\JsonSerializer;
+
 class TimepickerField extends BasicField {
+	public function has_serializer(): bool {
+		return true;
+	}
+
+	public function get_serializer(): Serializer {
+		return new JsonSerializer();
+	}
+
 	public function get_template_name(): string {
 		return 'timepicker';
 	}
diff --git a/src/Form/FormWithFields.php b/src/Form/FormWithFields.php
index ac0f159bda5a0c721ecb9ecd8995b902ed91b73a..de48e33d76b70c89a5f5aba5980b81e5f40260fc 100644
--- a/src/Form/FormWithFields.php
+++ b/src/Form/FormWithFields.php
@@ -94,8 +94,6 @@ class FormWithFields implements Form, ContainerForm, FieldProvider {
 
 	/**
 	 * Add array to update data.
-	 *
-	 * @param array|ContainerInterface $request new data to update.
 	 */
 	public function handle_request( array $request = [] ) {
 		if ( $this->updated_data === null ) {
diff --git a/src/Persistence/FieldPersistenceStrategy.php b/src/Persistence/FieldPersistenceStrategy.php
index 02f2d4ffd3a051c7abd34ca5c01d179afa7ad907..3102f1ce6f69d8f9dc6f790a9a885e92076d3e39 100644
--- a/src/Persistence/FieldPersistenceStrategy.php
+++ b/src/Persistence/FieldPersistenceStrategy.php
@@ -20,25 +20,29 @@ class FieldPersistenceStrategy {
 		$this->persistence = $persistence;
 	}
 
-	/**
-	 * Save fields data.
-	 */
+	/** @return void */
 	public function persist_fields( FieldProvider $fields_provider, array $data ) {
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
-			$this->persistence->set( $field_key, $field->get_serializer()->serialize( $data[ $field_key ] ) );
+			if ( $field->has_serializer() ) {
+				$this->persistence->set( $field_key, $field->get_serializer()->serialize( $data[ $field_key ] ) );
+			} else {
+				$this->persistence->set( $field_key, $data[ $field_key ] );
+			}
 		}
 	}
 
-	/**
-	 * Load fields data.
-	 */
+	/** @return void */
 	public function load_fields( FieldProvider $fields_provider ): array {
 		$data = [];
 		foreach ( $fields_provider->get_fields() as $field ) {
 			$field_key = $field->get_name();
 			try {
-				$data[ $field_key ] = $field->get_serializer()->unserialize( $this->persistence->get( $field_key ) );
+				if ( $field->has_serializer() ) {
+					$data[ $field_key ] = $field->get_serializer()->unserialize( $this->persistence->get( $field_key ) );
+				} else {
+					$data[ $field_key ] = $this->persistence->get( $field_key );
+				}
 			} catch ( NotFoundExceptionInterface $not_found ) {
 				// TODO: Logger
 				// LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
diff --git a/src/Serializer/NoSerialize.php b/src/Serializer/NoSerialize.php
deleted file mode 100644
index 371e8e75db3dd44eda7e9a0db99f9355e709729c..0000000000000000000000000000000000000000
--- a/src/Serializer/NoSerialize.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-namespace WPDesk\Forms\Serializer;
-
-use WPDesk\Forms\Serializer;
-
-class NoSerialize implements Serializer {
-	public function serialize( $value ): string {
-		return (string) $value;
-	}
-
-	public function unserialize( string $value ) {
-		return $value;
-	}
-
-}
diff --git a/templates/header.php b/templates/header.php
index e2384eae321d4ce9a89df6d87fa65527b2f61611..ec06536ea742126c9ee419c5a8a96fb8b03906fc 100644
--- a/templates/header.php
+++ b/templates/header.php
@@ -7,7 +7,6 @@
 
 $header_size = (int) $field->get_meta_value( 'header_size' ) ?: 2;
 $classes     = $field->has_classes() ? 'class="' . esc_attr( $field->get_classes() ) . '"' : '';
-
 ?>
 
 <?php if ( $field->has_label() ) : ?>
diff --git a/templates/input-image.php b/templates/input-image.php
index 9b5d63522fe8182d7bb4c1a40e62c91510f5cadd..5111c4c2c5af3cc159eb7e44597f4b46a5a5bf22 100644
--- a/templates/input-image.php
+++ b/templates/input-image.php
@@ -13,25 +13,17 @@ $media_container_id = 'media_' . sanitize_key( $field->get_id() );
 			id="<?php echo \esc_attr( $field->get_id() ); ?>"/>
 	<div class="custom-img-container">
 		<?php if ( $value ) : ?>
-			<img src="<?php echo \esc_attr( $value ); ?>" alt="" width="100"/>
+            <img src="<?php echo \esc_url( $value ) ?>" alt="" width="100"/>
 		<?php endif; ?>
-	</div>
-	<p class="hide-if-no-js">
-		<a class="upload-custom-img
-		<?php
-		if ( $value ) :
-			?>
-			hidden<?php endif ?>" href="<?php echo \esc_attr( $value ); ?>">
-			<?php esc_html_e( 'Set image', 'wp-forms' ); ?>
-		</a>
-		<a class="delete-custom-img
-		<?php
-		if ( ! $value ) :
-			?>
-			hidden<?php endif ?>" href="#">
-			<?php esc_html_e( 'Remove image', 'wp-forms' ); ?>
-		</a>
-	</p>
+    </div>
+    <p class="hide-if-no-js">
+        <a class="upload-custom-img <?php if ( $value ): ?>hidden<?php endif ?>" href="<?php echo \esc_url( $value ) ?>">
+			<?php \esc_html_e( 'Set image', 'wp-forms' ) ?>
+        </a>
+        <a class="delete-custom-img <?php if ( ! $value ): ?>hidden<?php endif ?>" href="#">
+			<?php \esc_html_e( 'Remove image', 'wp-forms' ) ?>
+        </a>
+    </p>
 </div>
 <script>
 	jQuery( function ( $ ) {