1

I have some sample objects that will be included in an ArrayList, and these items must appear in the specific format, the problem that each item must be is a new position of an array in the json return.

follow the code I have developed so far:

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class MyClass {
    
    String text = "hi";
    String language = "pt-br";
    String item = "1";
    
    public static void main(String args[]) {
        
        MyClass myObj1 = new MyClass();
        myObj1.text = "ola";
        myObj1.language = "pt-br";
        myObj1.item = "1";
 
        
        MyClass myObj2 = new MyClass();
        myObj2.text = "hi";
        myObj2.language = "en";
        myObj2.item = "1";

        
        MyClass myObj3 = new MyClass();
        myObj3.text = "holaa";
        myObj3.language = "es";
        myObj3.item = "2";
        
        MyClass myObj4 = new MyClass();
        myObj4.text = "olaaaaa";
        myObj4.language = "pt-br";
        myObj4.item = "2";

        MyClass myObj5 = new MyClass();
        myObj5.text = "helllooo";
        myObj5.language = "eng";
        myObj5.item = "3";

        
        List<MyClass> lang = new ArrayList<MyClass>();
        lang.add(myObj1);
        lang.add(myObj2);
        lang.add(myObj3);
        lang.add(myObj3);
        lang.add(myObj4);
        
        ArrayList<HashMap<String, String>> lista = new ArrayList<>();
        
        HashMap<String, String> mapa = new HashMap<>();
        
        for(int i = 0; i < lang.size();i++) {
            
            
            if(i > 0 && lang.get(i).item != lang.get(i-1).item) {
                
                lista.add(mapa);
                mapa.clear();
            }
            
            if(i == lang.size()-1){
                lista.add(mapa);
                mapa.clear();
            }
            
            mapa.put(lang.get(i).language, lang.get(i).text); 
            
            
        }
        
        
        
        System.out.println(lista.toString());
        
    }
}

which should be returned in this pattern:

[{
    "item_id": 1,
    "language": [{
        "pt-br": "ola",
        "en": "hii"
    }]
}, {
    "item_id": 2,
    "language": [{
        "es": "holaa",
        "pt-br": "olaaaaa"
    }]
}, {
    "item_id": 3,
    "language": [{
        "eng": "helllooo"
    }]
}]

the whole part of Spring is already implemented, I need to manipulate the result so that it is displayed correctly in my endpoint.

8
  • what's the issue now? Commented Oct 26, 2020 at 21:48
  • I cant return each item_id in same position of the arraylist Commented Oct 26, 2020 at 21:49
  • 1
    does the language property of each item have to be an array if it's always going to contain one object? Commented Oct 26, 2020 at 21:59
  • Yes, one array.. Commented Oct 26, 2020 at 22:06
  • Will the items in the input array always be guaranteed to be from 1, 2, 3, ..., up to n? with n being the number of items total. Or can there be gaps, for example the input array only has items 1, 3, and 5. Commented Oct 26, 2020 at 22:10

1 Answer 1

1

It is worth to implement an Item object and then transform the input List<MyClass> lang into List<Item>:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class Item {
    int item_id;
    List<Map<String, String>> language; // perhaps Map<String, String> would do fine

    Item(Map.Entry<Integer, Map<String, String>> entry) {
        this(entry.getKey(), entry.getValue());
    }
    
    Item(int id, Map<String, String> language) {
        this.item_id = id;
        this.language = Arrays.asList(language);
    }
    
    public String toString() {
        return String.format("item_id: %d,%nlanguage: %s%n", item_id, language);
    }
    // getters/setters
}
// MyClass.java
static List<Item> transform(List<MyClass> data) {
    return data
            .stream()
            .collect(Collectors.groupingBy(
                x -> Integer.parseInt(x.item), // to become int `item_id`
                LinkedHashMap::new,            // keep insertion order 
                Collectors.mapping(            // prepare map language:text
                    x -> Map.entry(x.language, x.text),  // Java 9
                    Collectors.toMap(
                        Map.Entry::getKey, 
                        Map.Entry::getValue, 
                        (a, b) -> a,           // merge occasional duplicates
                        LinkedHashMap::new)    // keep insertion order or TreeMap to sort by language
                    )
            ))
            .entrySet().stream()
            .map(Item::new)  // referencing overloaded constructor
            .collect(Collectors.toList());
}

Test

List<Item> items = transform(lang);
items.forEach(System.out::println);

Output

item_id: 1,
language: [{pt-br=ola, en=hi}]

item_id: 2,
language: [{es=holaa, pt-br=olaaaaa}]

item_id: 3,
language: [{eng=helllooo}]

Comments:

  • if Java 9 Map.entry cannot be used, it may be replaced with older new AbstractMap.SimpleEntry(x.language, x.text)
  • not sure whether list of maps is really needed in Item, it is provided just to meet the requirement as well as Arrays.asList(e.getValue()); the map instance should be fine.
  • in Item class use Jackson SnakeCaseStrategy in @JsonNaming annotation to guarantee proper serialization of item_id.

Update
Fixed and added an overloaded constructor in Item class, used method reference Item::new in transform

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.