3

I am needing to parse JSON data coming in from an outside source. The problem is sometimes and array of data is sent in and sometimes it come in as a single object, but the array and the single object have the same name.

{
 "OuterObject": {
 "Names":[
 {
 "name": "John Doe"
 },
 {
 "name": "William Watson"
 }
 ]
 }
}

But when the JSON array has only one element, it looks like this:

{
"OuterObject": {
 "Names": {
 "name": "John Doe"
 }
 }
}

My application needs to be able to handle either one of these, but not both at the same time.

This is what my Json parsed class looks like:

@JsonRootName("OuterObject")
public class OuterObject {
 @JsonProperty("Names")
 private Names names;
 @JsonProperty("Names")
 private List<Names> namesList;
 public Names getNames() {
 return names;
 }
 public void setNames(Names names) {
 this.names = names;
 }
 public List<Names> getNamesList() {
 return namesList;
 }
 public void setNamesList(List<Names> namesList) {
 this.namesList = namesList;
 }
}

However, it doesn't look like it will work to have the same json property name for both the list and the single object. It also doesn't appear to just use an array and have the single json object parse into the list. Does anyone know of any ways that my application can handle both json arrays and single json objects when the arrays and the objects have the same name?

asked Jul 13, 2017 at 21:19
7
  • 1
    Both examples you posted are invalid JSON. What do you really receive? You also don't say which JSON parser you're using. Commented Jul 13, 2017 at 21:23
  • Please state what you have tried so far. Are you using a Jackson ObjectMapper? Commented Jul 13, 2017 at 21:24
  • Edited to make JSON valid. Commented Jul 13, 2017 at 21:30
  • Possible duplicate of Gson: How do I parse polymorphic values that can be either lists or strings? Commented Jul 13, 2017 at 21:30
  • Yes, I am using the Jackson ObjectMapper as follows: OuterObject myOuterObject = objectMapper.readValue(jsonString, OuterObject.class). Commented Jul 13, 2017 at 21:32

4 Answers 4

4

You just need to use a single field of type List<Names>, and activate the feature ACCEPT_SINGLE_VALUE_AS_ARRAY

YourClass result = mapper.reader(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
 .forType(YourClass.class)
 .readValue(json);
answered Jul 14, 2017 at 6:12
Sign up to request clarification or add additional context in comments.

Comments

1

I have used following method for convert JSONArray, if it is only one JSONObject.

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
private JSONArray getJSONArray(JSONObject json, String field) {
 JSONArray array;
 if(json.get(field) instanceof JSONObject){
 array = new JSONArray();
 array.add(json.get(field));
 }else{
 array = json.getJSONArray(field);
 }
 return array;
 }
answered Mar 11, 2019 at 6:23

Comments

0

There is simpler way to activate feature:

 @JsonFormat(with=JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
 @JsonProperty("Names")
 private List<Names> namesList;
answered Apr 17, 2024 at 14:57

Comments

-1

Convert your json to Map then use your code to get the desired result.

ObjectMapper mapper = new ObjectMapper();
 Map<String, Object> map = mapper.convertValue(json, Map.class);

or better

Map<String, Object> map = mapper.convertValue(json, new TypeReference<Map<String, Object>>() {});
answered Jul 14, 2017 at 5:14

2 Comments

If you think it's a duplicate of that question, then mark it as such. But it's not, since the question is about Jackson, not Gson.
Thanks. Jackson was mentioned in the later comment. I missed that part.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.