feat: implement map-object conversion with a safer method

If you still want to use the unsafe version, please use
com.onixbyte:map-util-unsafe.
This commit is contained in:
zihluwang
2024-12-26 20:15:38 +08:00
parent 8f6dfce4b3
commit 2d3a0745f5
2 changed files with 21 additions and 92 deletions
@@ -31,7 +31,7 @@ import java.util.Optional;
* Please see documentation for more information.
*
* @author zihluwang
* @version 1.4.2
* @version 1.7.0
* @since 1.0.0
*/
@Slf4j
@@ -42,14 +42,11 @@ public final class MapUtil {
*
* @param <T> the type of the object
* @param entity the object to be converted to a map
* @param adapters adapts the entity for mapping to a map
* @param adapter adapts the entity for mapping to a map
* @return a map representing the fields and their values of the object
*/
public static <T> Map<String, Object> objectToMap(T entity,
Map<String, ObjectMapAdapter<T, ?>> adapters) {
var resultMap = new HashMap<String, Object>();
adapters.forEach((fieldName, adapter) -> resultMap.put(fieldName, adapter.fetch(entity)));
return resultMap;
public static <T> Map<String, Object> objectToMap(T entity, ObjectMapAdapter<T> adapter) {
return adapter.toMap(entity);
}
/**
@@ -57,64 +54,17 @@ public final class MapUtil {
* map entries.
*
* @param objectMap the map representing the fields and their values
* @param entity an empty entity of the target class
* @param adapters the adapters to execute the setter for the entity
* @param adapter the adapter to execute the setter for the entity
* @param <T> the type of the object to be created
* @return an object of the specified type with the field values set from the map
*/
public static <T> T mapToObject(Map<String, Object> objectMap,
T entity,
Map<String, ObjectMapAdapter<T, ?>> adapters) {
adapters.forEach((fieldName, adapter) -> Optional.ofNullable(objectMap)
.map((data) -> data.get(fieldName))
.ifPresent((fieldValue) -> adapter.setValue(entity, fieldValue)));
return entity;
public static <T> T mapToObject(Map<String, Object> objectMap, ObjectMapAdapter<T> adapter) {
return adapter.toObject(objectMap);
}
/**
* Retrieves the value of a field from an object using reflection.
*
* @param <E> the type of the entity
* @param <T> the type of the field value
* @param entity the object from which to retrieve the field value
* @param adapter the adapter to execute the getter
* @return the value of the field in the object, or null if the field does not exist or cannot
* be accessed
* Private constructor prevent class being instantiated.
*/
public static <E, T> T getFieldValue(E entity, ObjectMapAdapter<E, T> adapter) {
return adapter.fetch(entity);
}
/**
* Sets the value of a field in an object using reflection.
*
* @param <E> the type of the entity
* @param <T> the type of the field value
* @param entity the object in which to set the field value
* @param adapter the adapter to execute the setter
* @param fieldValue the value to be set
*/
public static <E, T> void setFieldValue(E entity,
ObjectMapAdapter<E, T> adapter,
Object fieldValue) {
adapter.setValue(entity, fieldValue);
}
/**
* Casts the specified value to the required type with Optional.
*
* @param value the value to be cast
* @param requiredType the type to which the value should be cast
* @param <T> the type to which the value should be cast
* @return the cast value, or {@code null} if the value is not an instance of the requiredType
*/
public static <T> T cast(Object value, Class<T> requiredType) {
return Optional.ofNullable(requiredType)
.filter((clazz) -> clazz.isInstance(value))
.map((clazz) -> clazz.cast(value))
.orElse(null);
}
private MapUtil() {
}
}
@@ -17,53 +17,32 @@
package com.onixbyte.devkit.utils;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.Map;
/**
* Adapts an Object to a Map, making conversion between Map and Object much more safe.
*
* @param <E> entity type
* @param <T> field type
* @author zihluwang
* @version 1.4.2
* @version 1.7.0
* @since 1.4.2
*/
public class ObjectMapAdapter<E, T> {
private final Function<E, T> getter;
private final BiConsumer<E, Object> setter;
public interface ObjectMapAdapter<T> {
/**
* Create an adapter.
* Convert an object to a map.
*
* @param getter the getter of the field
* @param setter the setter of the field
* @param element the element that will be converted to Map
* @return a Map that is converted from the element
*/
public ObjectMapAdapter(Function<E, T> getter, BiConsumer<E, Object> setter) {
this.getter = getter;
this.setter = setter;
}
Map<String, Object> toMap(T element);
/**
* Get data from the entity.
* Convert a Map to an object.
*
* @param entity the source of the data
* @return the data
* @param map the map that will be converted to Object
* @return the object that is converted from the Map
*/
public T fetch(E entity) {
return getter.apply(entity);
}
/**
* Set value to the entity.
*
* @param entity the target of the data
* @param value the value
*/
public void setValue(E entity, Object value) {
setter.accept(entity, value);
}
T toObject(Map<String, Object> map);
}