@@ -95,7 +95,8 @@ public class U<T> extends com.github.underscore.U<T> {
9595
9696 public enum Mode {
9797 REPLACE_SELF_CLOSING_WITH_NULL ,
98- REPLACE_SELF_CLOSING_WITH_EMPTY
98+ REPLACE_SELF_CLOSING_WITH_EMPTY ,
99+ REPLACE_EMPTY_VALUE_WITH_NULL
99100 }
100101
101102 public U (final Iterable <T > iterable ) {
@@ -1521,9 +1522,15 @@ public static List<String> stringToPath(final String string) {
15211522 return result ;
15221523 }
15231524
1525+ private enum OperationType {
1526+ GET ,
1527+ SET ,
1528+ REMOVE
1529+ }
1530+
15241531 @ SuppressWarnings ("unchecked" )
1525- private static <T > T baseGetAndSet (final Map <String , Object > object , final String path ,
1526- final Optional < Object > value ) {
1532+ private static <T > T baseGetOrSetOrRemove (final Map <String , Object > object , final String path ,
1533+ final Object value , OperationType operationType ) {
15271534 final List <String > paths = stringToPath (path );
15281535 int index = 0 ;
15291536 final int length = paths .size ();
@@ -1551,56 +1558,44 @@ private static <T> T baseGetAndSet(final Map<String, Object> object, final Strin
15511558 index += 1 ;
15521559 }
15531560 if (index > 0 && index == length ) {
1554- if (value .isPresent ()) {
1555- if (savedLocalObject instanceof Map ) {
1556- ((Map ) savedLocalObject ).put (savedPath , value .get ());
1557- } else {
1558- ((List ) savedLocalObject ).set (Integer .parseInt (savedPath ), value .get ());
1559- }
1560- }
1561+ checkSetAndRemove (value , operationType , savedLocalObject , savedPath );
15611562 return (T ) localObject ;
15621563 }
15631564 return null ;
15641565 }
15651566
1567+ @ SuppressWarnings ("unchecked" )
1568+ private static void checkSetAndRemove (Object value , OperationType operationType , Object savedLocalObject ,
1569+ String savedPath ) {
1570+ if (operationType == OperationType .SET ) {
1571+ if (savedLocalObject instanceof Map ) {
1572+ ((Map ) savedLocalObject ).put (savedPath , value );
1573+ } else {
1574+ ((List ) savedLocalObject ).set (Integer .parseInt (savedPath ), value );
1575+ }
1576+ } else if (operationType == OperationType .REMOVE ) {
1577+ if (savedLocalObject instanceof Map ) {
1578+ ((Map ) savedLocalObject ).remove (savedPath );
1579+ } else {
1580+ ((List ) savedLocalObject ).remove (Integer .parseInt (savedPath ));
1581+ }
1582+ }
1583+ }
1584+
15661585 private static Map .Entry getMapEntry (Map map ) {
15671586 return map .isEmpty () ? null : (Map .Entry ) map .entrySet ().iterator ().next ();
15681587 }
15691588
15701589 public static <T > T get (final Map <String , Object > object , final String path ) {
1571- return baseGetAndSet (object , path , Optional . absent () );
1590+ return baseGetOrSetOrRemove (object , path , null , OperationType . GET );
15721591 }
15731592
15741593 public static <T > T set (final Map <String , Object > object , final String path , Object value ) {
1575- return baseGetAndSet (object , path , Optional .of (value ));
1576- }
1577-
1578- @ SuppressWarnings ("unchecked" )
1579- public static Map <String , Object > remove (final Map <String , Object > map , final String key ) {
1580- Map <String , Object > outMap = newLinkedHashMap ();
1581- for (Map .Entry <String , Object > entry : map .entrySet ()) {
1582- if (!entry .getKey ().equals (key )) {
1583- outMap .put (entry .getKey (), makeObjectForRemove (entry .getValue (), key ));
1584- }
1585- }
1586- return outMap ;
1594+ return baseGetOrSetOrRemove (object , path , value , OperationType .SET );
15871595 }
15881596
1589- @ SuppressWarnings ("unchecked" )
1590- private static Object makeObjectForRemove (Object value , final String key ) {
1591- final Object result ;
1592- if (value instanceof List ) {
1593- List <Object > values = newArrayList ();
1594- for (Object item : (List ) value ) {
1595- values .add (item instanceof Map ? remove ((Map <String , Object >) item , key ) : item );
1596- }
1597- result = values ;
1598- } else if (value instanceof Map ) {
1599- result = remove ((Map <String , Object >) value , key );
1600- } else {
1601- result = value ;
1602- }
1603- return result ;
1597+ public static <T > T remove (final Map <String , Object > object , final String path ) {
1598+ return baseGetOrSetOrRemove (object , path , null , OperationType .REMOVE );
16041599 }
16051600
16061601 @ SuppressWarnings ("unchecked" )
@@ -2267,6 +2262,8 @@ public static String xmlToJson(String xml, Json.JsonStringBuilder.Step identStep
22672262 result = Json .toJson (replaceSelfClosingWithNull ((Map ) object ), identStep );
22682263 } else if (mode == Mode .REPLACE_SELF_CLOSING_WITH_EMPTY ) {
22692264 result = Json .toJson (replaceSelfClosingWithEmpty ((Map ) object ), identStep );
2265+ } else if (mode == Mode .REPLACE_EMPTY_VALUE_WITH_NULL ) {
2266+ result = Json .toJson (replaceEmptyValueWithNull ((Map ) object ), identStep );
22702267 } else {
22712268 result = Json .toJson ((Map ) object , identStep );
22722269 }
@@ -2416,6 +2413,36 @@ private static Object makeObjectSelfClose(Object value, String newValue) {
24162413 return result ;
24172414 }
24182415
2416+ @ SuppressWarnings ("unchecked" )
2417+ public static Map <String , Object > replaceEmptyValueWithNull (Map <String , Object > map ) {
2418+ if (map .isEmpty ()) {
2419+ return null ;
2420+ }
2421+ Map <String , Object > outMap = newLinkedHashMap ();
2422+ for (Map .Entry <String , Object > entry : map .entrySet ()) {
2423+ outMap .put (String .valueOf (entry .getKey ()),
2424+ makeObjectEmptyValue (entry .getValue ()));
2425+ }
2426+ return outMap ;
2427+ }
2428+
2429+ @ SuppressWarnings ("unchecked" )
2430+ private static Object makeObjectEmptyValue (Object value ) {
2431+ final Object result ;
2432+ if (value instanceof List ) {
2433+ List <Object > values = newArrayList ();
2434+ for (Object item : (List ) value ) {
2435+ values .add (item instanceof Map ? replaceEmptyValueWithNull ((Map ) item ) : item );
2436+ }
2437+ result = values ;
2438+ } else if (value instanceof Map ) {
2439+ result = replaceEmptyValueWithNull ((Map ) value );
2440+ } else {
2441+ result = value ;
2442+ }
2443+ return result ;
2444+ }
2445+
24192446 public static long gcd (long value1 , long value2 ) {
24202447 if (value1 == 0 ) {
24212448 return value2 ;
@@ -2456,6 +2483,16 @@ public Builder set(final String path, final Object value) {
24562483 return this ;
24572484 }
24582485
2486+ public Builder remove (final String key ) {
2487+ U .remove (data , key );
2488+ return this ;
2489+ }
2490+
2491+ public Builder clear () {
2492+ data .clear ();
2493+ return this ;
2494+ }
2495+
24592496 public Builder add (final Builder builder ) {
24602497 data .put (String .valueOf (data .size ()), builder .build ());
24612498 return this ;
@@ -2522,6 +2559,16 @@ public ArrayBuilder set(final int index, final Object value) {
25222559 return this ;
25232560 }
25242561
2562+ public ArrayBuilder remove (final int index ) {
2563+ data .remove (index );
2564+ return this ;
2565+ }
2566+
2567+ public ArrayBuilder clear () {
2568+ data .clear ();
2569+ return this ;
2570+ }
2571+
25252572 public ArrayBuilder add (final ArrayBuilder builder ) {
25262573 data .addAll (builder .build ());
25272574 return this ;
0 commit comments