Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,11 @@ public void setDate(Object obj, Date value) {
}

public void setObject(Object obj, Object value) {
setObjectAttribute(obj, DataConverter.toType(getDataType(), value ));
// ADR-0039: use the RESOLVING, array-aware getEffectiveDataType() -- the field's SCALAR
// getDataType() corrupted a List for an isArray field (e.g. comma-joining a STRING array
// into a single string) before setObjectAttribute's own instanceof check rejected it.
// getEffectiveDataType() is a strict no-op for every non-array field (#275 carry-forward).
setObjectAttribute(obj, DataConverter.toType(getEffectiveDataType(), value ));
}

public void setObjectArray(Object obj, List<?> value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,14 @@ protected void readFieldValue(MetaObject mo, MetaField mf, Object vo,
// nothing that parsed before stops parsing). String -> tolerant ISO parse
// (TemporalWireFormat). Array: element-wise into a List<Date> via
// setObjectArray, skipping context.deserialize(el, List.class), which yields a
// type-losing List<Double>. setObjectArray only bypasses MetaField's OWN
// DataConverter.toType call; setObjectAttribute still routes through
// AbstractObjectRepresentation.setValue, which unconditionally applies
// DataConverter.toType(effectiveDataType, value) -- and DataConverter's
// DATE_ARRAY case is unimplemented (unsupported()). So today this branch
// throws UnsupportedOperationException for a non-empty date array on the
// default (non-proxy) representation path; it becomes correct once
// DataConverter grows a DATE_ARRAY conversion.
// type-losing List<Double>. setObjectArray routes through
// AbstractObjectRepresentation.setValue, which applies
// DataConverter.toType(effectiveDataType, value) -- backed, since the #275
// carry-forward unit, by DataConverter.toDateArray. This branch genuinely
// round-trips a date array end to end today, INCLUDING a null element (see
// readDateElement's isJsonNull() guard -- required because the write side,
// MetaObjectSerializer, deliberately emits JsonNull.INSTANCE at a null element
// position; see GsonArrayWriteRoundTripTest's Step 3b/A6 coverage).
if (mf.isArrayType() && el.isJsonArray()) {
List<Date> dates = new ArrayList<>();
for (JsonElement item : el.getAsJsonArray()) {
Expand Down Expand Up @@ -203,8 +203,15 @@ protected void readFieldValue(MetaObject mo, MetaField mf, Object vo,
}
}

/** Single JSON array element of a DATE-array field: number -> epoch millis, string -> tolerant ISO parse. */
/** Single JSON array element of a DATE-array field: null -> null (JsonNull.getAsString()
* throws UnsupportedOperationException, so this must be checked before isJsonPrimitive --
* JsonNull is not a JsonPrimitive), number -> epoch millis, string -> tolerant ISO parse.
* Mirrors what MetaObjectSerializer.writeField's DATE-array branch emits at a null element
* position (JsonNull.INSTANCE), so a null element round-trips instead of throwing. */
private Date readDateElement(MetaField mf, JsonElement el) {
if (el.isJsonNull()) {
return null;
}
if (el.isJsonPrimitive() && el.getAsJsonPrimitive().isNumber()) {
return new Date(el.getAsLong());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.metaobjects.loader.MetaDataLoader;
import com.metaobjects.object.MetaObject;
import com.metaobjects.object.MetaObjectAware;
import com.metaobjects.util.DataConverter;
import com.google.gson.*;

import static com.metaobjects.io.json.JsonIOUtil.*;
Expand Down Expand Up @@ -94,7 +95,13 @@ protected void writeField(MetaObject mo, MetaField mf, Object vo,
} else {
JsonArray arr = new JsonArray();
for (Object o : dates) {
java.util.Date d = (java.util.Date) o;
// C1: route through the shared DataConverter.toDate(Object) rather
// than a hard (Date) cast -- matches the non-array DATE branch below
// (mf.getDate(vo) is itself backed by DataConverter.toDate), and
// accepts the same scalar inputs that converter always has, instead
// of throwing a bare ClassCastException for anything not already a
// java.util.Date.
java.util.Date d = DataConverter.toDate(o);
if (d == null) arr.add(JsonNull.INSTANCE);
else arr.add(TemporalWireFormat.format(mf, d));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ public static Object toType( DataTypes dataType, Object val ) {

case BYTE_ARRAY://return toByteArray( val );
case SHORT_ARRAY: //return toShortArray( val );
case DATE_ARRAY: //toDateArray( val );
return unsupported(dataType,val);

case DATE_ARRAY: return toDateArray( val );
case STRING_ARRAY: return toStringArray( val );
case OBJECT_ARRAY: return toObjectArray( val );

Expand Down Expand Up @@ -755,6 +755,33 @@ public static List<Boolean> toBooleanArray(Object val) {
}
}

/**
* Convert value to Date array (List&lt;Date&gt;)
*/
public static List<Date> toDateArray(Object val) {
if (val == null) return null;

if (val instanceof List<?>) {
List<?> list = (List<?>) val;
return list.stream()
.map(DataConverter::toDate)
.collect(java.util.stream.Collectors.toList());
} else if (val instanceof String) {
String s = (String) val;
if (s.trim().isEmpty()) return new java.util.ArrayList<>();

if (s.contains(",")) {
return java.util.Arrays.stream(s.split(","))
.map(item -> toDate(item.trim()))
.collect(java.util.stream.Collectors.toList());
} else {
return java.util.Arrays.asList(toDate(s.trim()));
}
} else {
return java.util.Arrays.asList(toDate(val));
}
}

/**
* Convert value to Double array (List&lt;Double&gt;)
*/
Expand Down
Loading
Loading