JsonMerge got unexpected result for List
See original GitHub issueHi Experts,
I got unexpected (but maybe as designed) result using JsonMerge for a List merge. For a short summary, I want to merge below Json1 with Json2: Json1:
{"titles":["Mr","Mrs"]}
Json2:
{"titles":["mr","mrs"]}
I expect got Json2, but I got below Json3: Json3:
{"titles":["Mr","Mrs","mr","mrs"]}
There has a description in JSON Merge Patch.
If the patch is anything other than an object, the result will always be to replace the entire target with the entire patch.
And there has a sample in section 3. Sample
of this spec.
Based on this spec, I expected Json2. But I think maybe it will be better to make the behavior configurable, e.g. replace, add, merge with diff, etc.
I also tried merging Json1 with a same List, then I got below which is also unexpected.
{"titles":["Mr","Mrs","Mr","Mrs"]}
It looks the behavior of Merge List is just add
.
Below is the code to reproduce, Pls copy to a java file and run.
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonMerge;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
public class JsonMergeTEst {
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
List<String> list1 = new ArrayList<>();
list1.add("Mr");
list1.add("Mrs");
List<String> list2 = new ArrayList<>();
list2.add("mr");
list2.add("mrs");
Title title1 = new Title();
title1.setTitles(list1);
JsonNode title1Node = objectMapper.valueToTree(title1);
Title title2 = new Title();
title2.setTitles(list2);
JsonNode title2Node = objectMapper.valueToTree(title2);
ObjectReader objectReader = objectMapper.readerForUpdating(title1Node);
JsonNode title3 = objectReader.readValue(title2Node);
System.out.println(objectMapper.writeValueAsString(title3));
// ObjectReader objectReader2 = objectMapper.readerForUpdating(title1);
// Title title4 = objectReader2.readValue(title2Node);
// System.out.println(objectMapper.writeValueAsString(title4));
}
public static class Title {
@JsonMerge
List<String> titles = null;
public List<String> getTitles() {
return titles;
}
public void setTitles(List<String> titles) {
this.titles = titles;
}
}
}
In the code I also tried using class Title
instead of JsonNode
as input of readerForUpdating
, but still get same result.
Thanks very much.
Issue Analytics
- State:
- Created 4 years ago
- Comments:12 (7 by maintainers)
Top GitHub Comments
Interesting… I think functionality you are using is reasonable and should work, however, it may be bit fragile (i.e. could not work for some specific case of 3rd party deserializers). One thing that could be helpful against regressions would be if you wanted to submit a unit test for
jackson-databind
that does simplified version of your real use case – that would at least make it less likely databind itself would be changed in a way that breaks the logic (there are tests for keeping context info accurate but coverage is quite shallow).One question however: did you try overriding
method? That is what merging use case should call, with default impl of
so overriding of this (or, method
handleBadMerge()
inDeserializationContext
but that’s more work, less robust) might work. Or is that called on wrong object, wrt what you need?At this point not quite sure what could be done here; closing. May be re-filed with a specific description of issue (possible referencing this issue for background if that helps).