I'm using the Gson library and jakarta. Although I have been able to use the conversion in CarrinhoResource.java as below, my ClienteTest.java cannot use the String content (already in json) inside the cart. I cant run my test a just only message into my intellij is (Cannot resolve method 'fromJson(java.lang.String)').
Can someone help me?
Class CarrinhoResource.java
package br.com.alura.loja.resource;
import br.com.alura.loja.dao.CarrinhoDAO;
import br.com.alura.loja.modelo.Carrinho;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
#Path("/v1/carrinhos")
public class CarrinhoResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public String busca(){
Carrinho carrinho = new CarrinhoDAO().busca(1L);
return carrinho.toJson();
}
}
Carrinho.java
package br.com.alura.loja.modelo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.google.gson.Gson;
public class Carrinho {
private List<Produto> produtos = new ArrayList<Produto>();
private String rua;
private String cidade;
private long id;
public Carrinho adiciona(Produto produto) {
produtos.add(produto);
return this;
}
public Carrinho para(String rua, String cidade) {
this.rua = rua;
this.cidade = cidade;
return this;
}
public Carrinho setId(long id) {
this.id = id;
return this;
}
public String getRua() {
return rua;
}
public void setRua(String rua) {
this.rua = rua;
}
public void setCidade(String cidade) {
this.cidade = cidade;
}
public long getId() {
return id;
}
public void remove(long id) {
for (Iterator iterator = produtos.iterator(); iterator.hasNext();) {
Produto produto = (Produto) iterator.next();
if(produto.getId() == id) {
iterator.remove();
}
}
}
public void troca(Produto produto) {
remove(produto.getId());
adiciona(produto);
}
public void trocaQuantidade(Produto produto) {
for (Iterator iterator = produtos.iterator(); iterator.hasNext();) {
Produto p = (Produto) iterator.next();
if(p.getId() == produto.getId()) {
p.setQuantidade(produto.getQuantidade());
return;
}
}
}
public List<Produto> getProdutos() {
return produtos;
}
public String toJson() {
return new Gson().toJson(this);
}
}
ClienteTest.java
package br.com.alura.loja;
import br.com.alura.loja.modelo.Carrinho;
import com.google.gson.*;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import org.junit.Assert;
import org.junit.Test;
public class ClienteTest {
#Test
public void testaConexaoServidor() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8085");
String conteudo = target.path("/v1/carrinhos").request().get(String.class);
Carrinho carrinho = (Carrinho) new Gson().fromJson(conteudo); **//Cannot resolve method 'fromJson(java.lang.String)'/**
System.out.println(carrinho);
Assert.assertEquals("Rua Vergueiro, 3185", carrinho.getRua());
}
}
Carrinho carrinho = (Carrinho) new Gson().fromJson(conteudo); **//Cannot resolve method 'fromJson(java.lang.String)'/**
The reason for this is that there is no Gson.fromJson(String) method, see the Gson class documentation. For deserialization Gson needs to know which type you are expecting, so all fromJson methods have a second parameter representing the type.
You can simply change your code to:
Carrinho carrinho = new Gson().fromJson(conteudo, Carrinho.class);
Need to convert below JSON Object to String JAVA, getting stuck how to do with nested array. Below is the JSON object:
{
"url": "https://www.apple.com",
"defer_time": 5,
"email": true,
"mac_res": "1024x768",
"win_res": "1366X768",
"smart_scroll": true,
"layout": "portrait",
"configs": {
"windows 10": {
"chrome": [
"76",
"75"
],
"firefox": [
"67",
"66"
]
},
"macos mojave": {
"chrome": [
"76",
"75"
],
"firefox": [
"67",
"66"
]
}
}
}
Currently, I am using JSONObject and JSONArray to write the code, but not able to get it proper for nested array.
Any help will be appreciated, many thanks !!
this code will clear everything for you i hope. first to read json file you can open it with stream, them pass stream to JSONObject directly, because it has constructor for doing such trick, or append string from file to StringBuilder, then pass stringbuilder to string to JSONObject.
public static void main(String[] args) {
try(BufferedReader fileReader = new BufferedReader(new FileReader("test.json"))){
String line="";
StringBuilder stringBuilder = new StringBuilder();
while ((line = fileReader.readLine()) !=null){
stringBuilder.append(line);
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
// to add single values yo your array.
// you can do something like this
JSONObject config = jsonObject.getJSONObject("configs");
JSONObject macos_mojave = config.getJSONObject("macos mojave");
JSONArray jsonArray = macos_mojave.getJSONArray("chrome"); // this way you will reach the array
jsonArray.put("77"); // then you can add them new values
jsonArray.put("78");
System.out.println(jsonArray.toList()); //will print your array content
} catch (IOException e){
e.printStackTrace();
}
JSONArray jsonArray = new JSONArray(); // this is what you call single values, it is array
jsonArray.put(75);
jsonArray.put(76);
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("Something", jsonArray);
}
you can write them back to file like this
//if you write them back to file you will see that 77 and 78 was added to chrome array (single values as you call them)
try(FileWriter fileWriter = new FileWriter("test.json")){
fileWriter.write(jsonObject.toString(5));
}catch (IOException ignore){
}
and after opening test.json file result will be next
{
"win_res": "1366X768",
"layout": "portrait",
"configs": {
"windows 10": {
"chrome": [
"76",
"75"
],
"firefox": [
"67",
"66"
]
},
"macos mojave": {
"chrome": [
"76",
"75",
"77",
"78"
],
"firefox": [
"67",
"66"
]
}
},
"smart_scroll": true,
"defer_time": 5,
"mac_res": "1024x768",
"url": "https://www.apple.com",
"email": true
}
as you see 77 and 78 was appended to "chrome" JSONArray. file will not track order because behind the scenes it is using HashMap.
Try to parse your string to the example Java object. Then call the toString method.
ObjectMapper mapper = newObjectMapper();
String jsonInString = "your string";
//JSON from String to Object
Example yourExample = mapper.readValue(jsonInString, Example.class);
yourExample.toString();
-----------------------------------com.example.Configs.java-----------------------------------
package com.example;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"windows 10",
"macos mojave"
})
public class Configs {
#JsonProperty("windows 10")
private Windows10 windows10;
#JsonProperty("macos mojave")
private MacosMojave macosMojave;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("windows 10")
public Windows10 getWindows10() {
return windows10;
}
#JsonProperty("windows 10")
public void setWindows10(Windows10 windows10) {
this.windows10 = windows10;
}
#JsonProperty("macos mojave")
public MacosMojave getMacosMojave() {
return macosMojave;
}
#JsonProperty("macos mojave")
public void setMacosMojave(MacosMojave macosMojave) {
this.macosMojave = macosMojave;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
#Override
public String toString() {
return new ToStringBuilder(this).append("windows10", windows10).append("macosMojave", macosMojave).append("additionalProperties", additionalProperties).toString();
}
#Override
public int hashCode() {
return new HashCodeBuilder().append(windows10).append(additionalProperties).append(macosMojave).toHashCode();
}
#Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Configs) == false) {
return false;
}
Configs rhs = ((Configs) other);
return new EqualsBuilder().append(windows10, rhs.windows10).append(additionalProperties, rhs.additionalProperties).append(macosMojave, rhs.macosMojave).isEquals();
}
}
-----------------------------------com.example.Example.java-----------------------------------
package com.example;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"url",
"defer_time",
"email",
"mac_res",
"win_res",
"smart_scroll",
"layout",
"configs"
})
public class Example {
#JsonProperty("url")
private String url;
#JsonProperty("defer_time")
private long deferTime;
#JsonProperty("email")
private boolean email;
#JsonProperty("mac_res")
private String macRes;
#JsonProperty("win_res")
private String winRes;
#JsonProperty("smart_scroll")
private boolean smartScroll;
#JsonProperty("layout")
private String layout;
#JsonProperty("configs")
private Configs configs;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("url")
public String getUrl() {
return url;
}
#JsonProperty("url")
public void setUrl(String url) {
this.url = url;
}
#JsonProperty("defer_time")
public long getDeferTime() {
return deferTime;
}
#JsonProperty("defer_time")
public void setDeferTime(long deferTime) {
this.deferTime = deferTime;
}
#JsonProperty("email")
public boolean isEmail() {
return email;
}
#JsonProperty("email")
public void setEmail(boolean email) {
this.email = email;
}
#JsonProperty("mac_res")
public String getMacRes() {
return macRes;
}
#JsonProperty("mac_res")
public void setMacRes(String macRes) {
this.macRes = macRes;
}
#JsonProperty("win_res")
public String getWinRes() {
return winRes;
}
#JsonProperty("win_res")
public void setWinRes(String winRes) {
this.winRes = winRes;
}
#JsonProperty("smart_scroll")
public boolean isSmartScroll() {
return smartScroll;
}
#JsonProperty("smart_scroll")
public void setSmartScroll(boolean smartScroll) {
this.smartScroll = smartScroll;
}
#JsonProperty("layout")
public String getLayout() {
return layout;
}
#JsonProperty("layout")
public void setLayout(String layout) {
this.layout = layout;
}
#JsonProperty("configs")
public Configs getConfigs() {
return configs;
}
#JsonProperty("configs")
public void setConfigs(Configs configs) {
this.configs = configs;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
#Override
public String toString() {
return new ToStringBuilder(this).append("url", url).append("deferTime", deferTime).append("email", email).append("macRes", macRes).append("winRes", winRes).append("smartScroll", smartScroll).append("layout", layout).append("configs", configs).append("additionalProperties", additionalProperties).toString();
}
#Override
public int hashCode() {
return new HashCodeBuilder().append(configs).append(winRes).append(deferTime).append(email).append(additionalProperties).append(macRes).append(layout).append(smartScroll).append(url).toHashCode();
}
#Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Example) == false) {
return false;
}
Example rhs = ((Example) other);
return new EqualsBuilder().append(configs, rhs.configs).append(winRes, rhs.winRes).append(deferTime, rhs.deferTime).append(email, rhs.email).append(additionalProperties, rhs.additionalProperties).append(macRes, rhs.macRes).append(layout, rhs.layout).append(smartScroll, rhs.smartScroll).append(url, rhs.url).isEquals();
}
}
-----------------------------------com.example.MacosMojave.java-----------------------------------
package com.example;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"chrome",
"firefox"
})
public class MacosMojave {
#JsonProperty("chrome")
private List<String> chrome = null;
#JsonProperty("firefox")
private List<String> firefox = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("chrome")
public List<String> getChrome() {
return chrome;
}
#JsonProperty("chrome")
public void setChrome(List<String> chrome) {
this.chrome = chrome;
}
#JsonProperty("firefox")
public List<String> getFirefox() {
return firefox;
}
#JsonProperty("firefox")
public void setFirefox(List<String> firefox) {
this.firefox = firefox;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
#Override
public String toString() {
return new ToStringBuilder(this).append("chrome", chrome).append("firefox", firefox).append("additionalProperties", additionalProperties).toString();
}
#Override
public int hashCode() {
return new HashCodeBuilder().append(firefox).append(additionalProperties).append(chrome).toHashCode();
}
#Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof MacosMojave) == false) {
return false;
}
MacosMojave rhs = ((MacosMojave) other);
return new EqualsBuilder().append(firefox, rhs.firefox).append(additionalProperties, rhs.additionalProperties).append(chrome, rhs.chrome).isEquals();
}
}
-----------------------------------com.example.Windows10.java-----------------------------------
package com.example;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"chrome",
"firefox"
})
public class Windows10 {
#JsonProperty("chrome")
private List<String> chrome = null;
#JsonProperty("firefox")
private List<String> firefox = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("chrome")
public List<String> getChrome() {
return chrome;
}
#JsonProperty("chrome")
public void setChrome(List<String> chrome) {
this.chrome = chrome;
}
#JsonProperty("firefox")
public List<String> getFirefox() {
return firefox;
}
#JsonProperty("firefox")
public void setFirefox(List<String> firefox) {
this.firefox = firefox;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
#Override
public String toString() {
return new ToStringBuilder(this).append("chrome", chrome).append("firefox", firefox).append("additionalProperties", additionalProperties).toString();
}
#Override
public int hashCode() {
return new HashCodeBuilder().append(firefox).append(additionalProperties).append(chrome).toHashCode();
}
#Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Windows10) == false) {
return false;
}
Windows10 rhs = ((Windows10) other);
return new EqualsBuilder().append(firefox, rhs.firefox).append(additionalProperties, rhs.additionalProperties).append(chrome, rhs.chrome).isEquals();
}
}
Here is how you could do it with BSON
import java.util.ArrayList;
import org.bson.Document;
Declare all the json objects and arrays you plan to use in your code.
Document root= new Document();
Document rootConfigs = new Document();
Document rootConfigsWindows10 = new Document();
ArrayList rootConfigsWindows10Chrome= new ArrayList();
ArrayList rootConfigsWindows10Firefox= new ArrayList();
Document rootConfigsMacosmojave = new Document();
ArrayList rootConfigsMacosmojaveChrome= new ArrayList();
ArrayList rootConfigsMacosmojaveFirefox= new ArrayList();
Assign out your strings and integers to the correct JSON documents.
root.append("url","https://www.apple.com");
root.append("defer_time",5);
root.append("email",true);
root.append("mac_res","1024x768");
root.append("win_res","1366X768");
root.append("smart_scroll",true);
root.append("layout","portrait");
rootConfigsWindows10Chrome.add("76");
rootConfigsWindows10Chrome.add("75");
rootConfigsWindows10Firefox.add("67");
rootConfigsWindows10Firefox.add("66");
rootConfigsMacosmojaveChrome.add("76");
rootConfigsMacosmojaveChrome.add("75");
rootConfigsMacosmojaveFirefox.add("67");
rootConfigsMacosmojaveFirefox.add("66");
Merge all the jsons together in the right order to form your nested JSON in the ROOT object
if (!rootConfigsWindows10Chrome.isEmpty()){
rootConfigsWindows10.append("chrome",rootConfigsWindows10Chrome);
}
if (!rootConfigsWindows10Firefox.isEmpty()){
rootConfigsWindows10.append("firefox",rootConfigsWindows10Firefox);
}
if (!rootConfigsWindows10.isEmpty()){
rootConfigs.append("windows 10",rootConfigsWindows10);
}
if (!rootConfigsMacosmojaveChrome.isEmpty()){
rootConfigsMacosmojave.append("chrome",rootConfigsMacosmojaveChrome);
}
if (!rootConfigsMacosmojaveFirefox.isEmpty()){
rootConfigsMacosmojave.append("firefox",rootConfigsMacosmojaveFirefox);
}
if (!rootConfigsMacosmojave.isEmpty()){
rootConfigs.append("macos mojave",rootConfigsMacosmojave);
}
if (!rootConfigs.isEmpty()){
root.append("configs",rootConfigs);
}
Output your JSON to see if it worked.
System.out.println(root.toJson());
I have the following XML:
<object>
<name>Test</name>
<bikes>
<bike key="Hello" value="World"/>
</bikes>
</object>
So I then have the following Objects:
#XmlRootElement
public class Object {
#XmlElement
private String name;
#XmlElement
private Bikes bikes;
public Object(String name, Bikes bikes) {
this.name = name;
this.bikes = bikes;
}
Bikes
public class Bikes{
private Map<String, String> bike = new HashMap();
#XmlElement
public Bikes(Map<String, String> bike) {
this.bike = bike;
}
I have tried to unmarshall the xml into the the above classes but I am not sure how.
Found a couple of answers on here but none seemed to work as I needed.
You shall be able to do it using adapter class. here is a working case.
Object.java
The class has XmlJavaTypeAdapter(BikeAdapter.class) annoted to bikes map. Adapter and wrapper class are defined here itself.
package testjaxb;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Object {
#XmlElement
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getBikes() {
return bikes;
}
public void setBikes(Map<String, String> bikes) {
this.bikes = bikes;
}
#XmlJavaTypeAdapter(BikeAdapter.class)
private Map<String, String> bikes;
public Object() {
}
}
class BikeWrapper {
#XmlElement(name = "bike")
List<Bike> bike = new ArrayList<Bike>();
}
class BikeAdapter extends XmlAdapter<BikeWrapper, Map<String, String>> {
public BikeWrapper marshal(Map<String, String> arg0) throws Exception {
BikeWrapper bw = new BikeWrapper();
List<Bike> bikes = new ArrayList<Bike>();
for (Map.Entry<String, String> entry : arg0.entrySet()) {
bikes.add(new Bike(entry.getKey(), entry.getValue()));
}
bw.bike = bikes;
return bw;
}
public Map<String, String> unmarshal(BikeWrapper arg0) throws Exception {
Map<String, String> r = new HashMap<String, String>();
for (Bike mapelement : arg0.bike) {
r.put(mapelement.getKey(), mapelement.getValue());
}
return r;
}
}
Bike.jaa
package testjaxb;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
#XmlAccessorType(XmlAccessType.FIELD)
public class Bike {
#XmlAttribute()
private String key;
public Bike() {
}
public Bike(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#XmlAttribute()
private String value;
public String toString() {
return "Bike : key-" + getKey() + ", value -" + getValue();
}
}
And here is your Main class to test.
package testjaxb;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class Main {
public static void main(String[] args) throws Exception {
String xmlString = "<object>\n"
+ " <name>Test</name>\n"
+ " <bikes>\n"
+ " <bike key=\"Hello\" value=\"World\"/>\n"
+ " </bikes>\n"
+ "</object>";
testjaxb.Object o = unmarshal(testjaxb.Object.class, xmlString);
System.out.println("Bike List.." + o.getBikes());
}
private static <C> C unmarshal(Class<C> c, String sampleXML) throws Exception {
JAXBContext jc = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StringReader reader = new StringReader(sampleXML);
//System.out.println("" + sampleXML);
return (C) unmarshaller.unmarshal(reader);
}
}
I need something like this -
<Token>
<HighLevel info-1="" info-2=""/>
<LowLevel>
<LowLevel info-key="" info-value=""/>
<LowLevel info-key="" info-value=""/>
....
</LowLevel>
</Token >
I've the Map for LowLevel element, whose entries I want to populate like above XML.
What could be the way to encapsulate/bind this using JAXB?
You could use a custom adapter for this. Example
//Token.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
class LowLevelToken {
#XmlAttribute(name = "info-key")
public String key;
#XmlAttribute(name = "info-value")
public String value;
private LowLevelToken() {}
public LowLevelToken(String key, String value) {
this.key = key;
this.value = value;
}
}
#XmlRootElement
class HighLevelToken {
#XmlAttribute(name = "info-1")
public String info1;
#XmlAttribute(name = "info-2")
public String info2;
private HighLevelToken() {}
public HighLevelToken(String info1, String info2) {
this.info1 = info1;
this.info2 = info2;
}
}
class TokenWrapper {
#XmlElement(name="LowLevel")
public List<LowLevelToken> tokens = new ArrayList<LowLevelToken>();
}
class TokenAdapter extends XmlAdapter<TokenWrapper, Map<String, String>> {
#Override
public TokenWrapper marshal(Map<String, String> lowlevelTokens)
throws Exception {
TokenWrapper wrapper = new TokenWrapper();
List<LowLevelToken> elements = new ArrayList<LowLevelToken>();
for (Map.Entry<String, String> property : lowlevelTokens.entrySet()) {
elements.add(new LowLevelToken(property.getKey(), property.getValue()));
}
wrapper.tokens = elements;
return wrapper;
}
#Override
public Map<String, String> unmarshal(TokenWrapper tokenWrapper) throws Exception {
Map<String, String> tokens = null;
if(tokenWrapper != null && tokenWrapper.tokens != null && !tokenWrapper.tokens.isEmpty()){
tokens = new HashMap<String, String>();
for(LowLevelToken token : tokenWrapper.tokens){
tokens.put(token.key, token.value);
}
}
return tokens;
}
}
#XmlRootElement(name = "Token")
public class Token {
HighLevelToken highLevel;
Map<String, String> lowLevel;
public HighLevelToken getHighLevel() {
return highLevel;
}
#XmlElement(name = "HighLevel")
public void setHighLevel(HighLevelToken highLevel) {
this.highLevel = highLevel;
}
public Map<String, String> getLowLevel() {
return lowLevel;
}
#XmlElement(name = "LowLevel")
#XmlJavaTypeAdapter(TokenAdapter.class)
public void setLowLevel(Map<String, String> lowLevel) {
this.lowLevel = lowLevel;
}
}
A sample program
import java.util.HashMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class JAXBExample {
public static void main(String[] args) {
Token token = new Token();
token.setHighLevel(new HighLevelToken("1", "2"));
token.setLowLevel(new HashMap<String, String>() {{ put("LK1", "LV1"); put("LK2", "LV2"); put("LK2", "LV2"); }});
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Token.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(token, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
This generates
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Token>
<HighLevel info-1="1" info-2="2"/>
<LowLevel>
<LowLevel info-key="LK2" info-value="LV2"/>
<LowLevel info-key="LK1" info-value="LV1"/>
</LowLevel>
</Token>
Update: After suggestion from one of the experts here, I have cleaned up the following Java code:
There is a class called MyRespModifier and it holds two inner static classes called ResponseMail and Response
I have rewritten this code Scala as an exercise. Scala version: 2.11.2. I am not happy with the results. It resembles Java, and looks like it could do with a large dose of idiomatic Scala from the ground up. I would like to accomplish a reduction in the no of lines and also on inspection of the code it should stand out as elegant Scala code.At least my goal is to understand how some Java constructs can be rewritten in idiomatic Scala.
The Scala equivalent is posted after the Java code:
import java.util.ArrayList;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.io.FileInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.ContentType;
public class MyRespModifier {
private static final String VERSION = "1.0.0";
private static final String USER_AGENT = "myuseragent/"+ VERSION + "java";
private static final String ARG_TO = "to[%d]";
private static final String ARG_TONAME = "toname[%d]";
private static final String ARG_CC = "cc[%d]";
private static final String ARG_FROM = "from";
private static final String ARG_FROMNAME = "fromname";
private static final String ARG_REPLYTO = "replyto";
private static final String ARG_SUBJECT = "subject";
private static final String ARG_CONTENTS = "content[%s]";
private static final String ARG_MYSMTPAPI = "x-respModifierSmtpApi";
private String apikey;
private String apivalue;
private String apiUrlBasePath;
private String port;
private String endpoint;
private CloseableHttpClient client;
public MyRespModifier() {
this.apiUrlBasePath = "api/responseshaper/response";
this.endpoint = "/myapi/mymail.dispatch.json";
this.client = HttpClientBuilder.create().setUserAgent(USER_AGENT).build();
}
public MyRespModifier setUrl(String url) {
this.apiUrlBasePath = apiUrlBasePath;
return this;
}
public MyRespModifier setEndpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}
public MyRespModifier setClient(CloseableHttpClient client) {
this.client = client;
return this;
}
public HttpEntity constructRespBody(ResponseEmail respEmail) {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("api_user", this.apikey);
builder.addTextBody("api_key", this.apivalue);
String[] tos = respEmail.getTos();
String[] tonames = respEmail.getToNames();
String[] ccs = respEmail.getCcs();
if (tos.length == 0) {
builder.addTextBody(String.format(ARG_TO, 0), respEmail.getFrom(), ContentType.create("text/plain", "UTF-8"));
}
for (int i = 0, len = tos.length; i < len; i++)
builder.addTextBody(String.format(ARG_TO, i), tos[i], ContentType.create("text/plain", "UTF-8"));
for (int i = 0, len = tonames.length; i < len; i++)
builder.addTextBody(String.format(ARG_TONAME, i), tonames[i], ContentType.create("text/plain", "UTF-8"));
for (int i = 0, len = ccs.length; i < len; i++)
builder.addTextBody(String.format(ARG_CC, i), ccs[i], ContentType.create("text/plain", "UTF-8"));
if (respEmail.getContentIds().size() > 0) {
Iterator it = respEmail.getContentIds().entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
builder.addTextBody(String.format(ARG_CONTENTS, entry.getKey()), (String) entry.getValue());
}
}
if (respEmail.getFrom() != null && !respEmail.getFrom().isEmpty())
builder.addTextBody(ARG_FROM, respEmail.getFrom(), ContentType.create("text/plain", "UTF-8"));
if (respEmail.getFromName() != null && !respEmail.getFromName().isEmpty())
builder.addTextBody(ARG_FROMNAME, respEmail.getFromName(), ContentType.create("text/plain", "UTF-8"));
if (respEmail.getReplyTo() != null && !respEmail.getReplyTo().isEmpty())
builder.addTextBody(ARG_REPLYTO, respEmail.getReplyTo(), ContentType.create("text/plain", "UTF-8"));
if (respEmail.getSubject() != null && !respEmail.getSubject().isEmpty())
builder.addTextBody(ARG_SUBJECT, respEmail.getSubject(), ContentType.create("text/plain", "UTF-8"));
String tmpString = respEmail.respModifierSmtpApi.jsonString();
if (!tmpString.equals("{}"))
builder.addTextBody(ARG_MYSMTPAPI, tmpString, ContentType.create("text/plain", "UTF-8"));
return builder.build();
} //end of method constructRespBody
public MyRespModifier.Response send(ResponseEmail respMail) throws RespModifierException {
HttpPost httppost = new HttpPost(this.apiUrlBasePath + this.endpoint);
httppost.setEntity(this.constructRespBody(respMail));
try {
HttpResponse res = this.client.execute(httppost);
return new MyRespModifier.Response(res.getStatusLine().getStatusCode(), EntityUtils.toString(res.getEntity()));
} catch (IOException e) {
throw new RespModifierException(e);
}
}
//*********************************************************************
public static class ResponseEmail {
private MyExperimentalApi respModifierSmtpApi;
private ArrayList<String> to;
private ArrayList<String> toname;
private ArrayList<String> cc;
private String from;
private String fromname;
private String replyto;
private String subject;
private String text;
private Map<String, String> contents;
private Map<String, String> headers;
public ResponseEmail () {
this.respModifierSmtpApi = new MyExperimentalApi();
this.to = new ArrayList<String>();
this.toname = new ArrayList<String>();
this.cc = new ArrayList<String>();
this.contents = new HashMap<String, String>();
this.headers = new HashMap<String, String>();
}
public ResponseEmail addTo(String to) {
this.to.add(to);
return this;
}
public ResponseEmail addTo(String[] tos) {
this.to.addAll(Arrays.asList(tos));
return this;
}
public ResponseEmail addTo(String to, String name) {
this.addTo(to);
return this.addToName(name);
}
public ResponseEmail setTo(String[] tos) {
this.to = new ArrayList<String>(Arrays.asList(tos));
return this;
}
public String[] getTos() {
return this.to.toArray(new String[this.to.size()]);
}
public ResponseEmail addSmtpApiTo(String to) {
this.respModifierSmtpApi.addTo(to);
return this;
}
public ResponseEmail addSmtpApiTo(String[] to) {
this.respModifierSmtpApi.addTos(to);
return this;
}
public ResponseEmail addToName(String toname) {
this.toname.add(toname);
return this;
}
public ResponseEmail addToName(String[] tonames) {
this.toname.addAll(Arrays.asList(tonames));
return this;
}
public ResponseEmail setToName(String[] tonames) {
this.toname = new ArrayList<String>(Arrays.asList(tonames));
return this;
}
public String[] getToNames() {
return this.toname.toArray(new String[this.toname.size()]);
}
public ResponseEmail addCc(String cc) {
this.cc.add(cc);
return this;
}
public ResponseEmail addCc(String[] ccs) {
this.cc.addAll(Arrays.asList(ccs));
return this;
}
public ResponseEmail setCc(String[] ccs) {
this.cc = new ArrayList<String>(Arrays.asList(ccs));
return this;
}
public String[] getCcs() {
return this.cc.toArray(new String[this.cc.size()]);
}
public ResponseEmail setFrom(String from) {
this.from = from;
return this;
}
public String getFrom() {
return this.from;
}
public ResponseEmail setFromName(String fromname) {
this.fromname = fromname;
return this;
}
public String getFromName() {
return this.fromname;
}
public ResponseEmail setReplyTo(String replyto) {
this.replyto = replyto;
return this;
}
public String getReplyTo() {
return this.replyto;
}
public ResponseEmail setSubject(String subject) {
this.subject = subject;
return this;
}
public String getSubject() {
return this.subject;
}
public ResponseEmail setText(String text) {
this.text = text;
return this;
}
public String getText() {
return this.text;
}
public JSONObject getFilters() {
return this.respModifierSmtpApi.getFilters();
}
public ResponseEmail addContentId(String attachmentName, String cid) {
this.contents.put(attachmentName, cid);
return this;
}
public Map getContentIds() {
return this.contents;
}
public ResponseEmail addHeader(String key, String val) {
this.headers.put(key, val);
return this;
}
public Map getHeaders() {
return this.headers;
}
public MyExperimentalApi getSMTPAPI() {
return this.respModifierSmtpApi;
}
}
public static class Response {
private int code;
private boolean success;
private String message;
public Response(int code, String msg) {
this.code = code;
this.success = code == 200;
this.message = msg;
}
public int getCode() {
return this.code;
}
public boolean getStatus() {
return this.success;
}
public String getMessage() {
return this.message;
}
}//end of class Response
You can change the imports to save some lines
import java.util.Arrays
import java.util.HashMap
import java.util.Iterator
becomes
import java.util.{Arrays, HashMap, Iterator}
The getters and setters can be generated for you. This is a feature of a Scala class if you declare the constructor parameter with val or var.
A simplified version of your class becomes:
class ResponseEmail(var to: ArrayList[String], var cc: ArrayList[String])
This getters are cc and to and the setters are cc_= and to_=
scala> res6.
asInstanceOf cc cc_= isInstanceOf to toString to_=