Created
April 3, 2022 16:51
-
-
Save andreacioni/3788ed96a0c705a4ed923aafcf6aa8ac to your computer and use it in GitHub Desktop.
DeepMerge Dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
emptyTarget(val) { | |
return val is List ? [] : {}; | |
} | |
dynamic cloneUnlessOtherwiseSpecified(value) { | |
print('$value'); | |
return isMergeableObject(value) | |
? deepmerge(emptyTarget(value), value) | |
: value; | |
} | |
List defaultArrayMerge(List target, List source) { | |
return [...target, ...source] | |
.map((element) => cloneUnlessOtherwiseSpecified(element)) | |
.toList(); | |
} | |
bool propertyIsOnObject(Map<dynamic, dynamic> object, dynamic property) { | |
return object.containsKey(property); | |
} | |
// Protects from prototype poisoning and unexpected merging up the prototype chain. | |
bool propertyIsUnsafe(target, key) { | |
return propertyIsOnObject(target, key); // Properties are safe to merge if they don't exist in the target yet | |
} | |
bool isMergeableObject(obj) { | |
return obj != null && (obj is List || obj is Map); | |
} | |
Map<dynamic, dynamic> mergeObject( | |
Map<dynamic, dynamic> target, Map<dynamic, dynamic> source) { | |
Map<dynamic, dynamic> destination = {}; | |
if (isMergeableObject(target)) { | |
for (final key in target.keys) { | |
destination[key] = cloneUnlessOtherwiseSpecified(target[key]); | |
} | |
} | |
for (final key in source.keys) { | |
if (propertyIsUnsafe(target, key)) { | |
continue; | |
} | |
print('T: $target S: $source'); | |
if (propertyIsOnObject(target, key) && isMergeableObject(source[key])) { | |
destination[key] = deepmerge(target[key], source[key]); | |
} else { | |
destination[key] = cloneUnlessOtherwiseSpecified(source[key]); | |
} | |
} | |
return destination; | |
} | |
deepmerge(dynamic target, dynamic source) { | |
final isList = target is List && source is List; | |
final isMap = target is Map && source is Map; | |
if (isMap) { | |
print(target); | |
return mergeObject(target, source); | |
} else if (isList) { | |
print('lizf $target $source'); | |
return defaultArrayMerge(target, source); | |
} else { | |
return cloneUnlessOtherwiseSpecified(source); | |
} | |
} | |
void main() { | |
print('ciao'); | |
final Map<String, dynamic> a = { | |
'zio': 1, | |
'rotolo': 2, | |
'pino': [4] | |
}; | |
final Map<String, dynamic> b = { | |
'zio': 'pane', | |
'giovannni': 'pallini', | |
'pino': [3] | |
}; | |
final r = deepmerge(a, b); | |
print('result: $r'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment