Implementing JAXB without POJO classes and with linkedHashmaps - java

I am trying to use JAXB implementation to convert my class objects to XML and vice versa.
I implemented this by observing a tutorial.
My XML looks like this
<Alphabet>
<a>Apple</a>
<b>Ball</b>
<c>Cat</c>
<d>Dog</d>
<e>Elephant</e>
<f>Fox</f>
</Alphabet>
I wrote the following classes
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
public class Alph {
#XmlElement
private LinkedHashMap<String, String> cLinkedHashMap = new
LinkedHashMap<String, String>();
protected void put(String theKey, String theValue) {
cLinkedHashMap.put(theKey, theValue);
}
protected String get(String theKey) {
return (String) cLinkedHashMap.get(theKey);
}
protected Set<Entry<String,String>> getCEntrySet() {
return cLinkedHashMap.entrySet();
}
protected LinkedHashMap<String, String> getCLinkedHashMap() {
return cLinkedHashMap;
}
public String toCXML() throws XMLHandlingException {
return null;
}
}
#XmlRootElement
public class Alphabet extends Alph {
public static Alphabet getInstance(String theAlphabetXML) throws
XMLHandlingException {
return XMLUtils.parseAlphabetXML(theAlphabetXML);
}
public String toCXML() throws XMLHandlingException {
return XMLUtils.getAlphabetXML(this);
}
}
I created the following XMLUtil Methods for marshalling and unmarshalling
public static String getAlphabetXML(Alph theAlphabet) throws XMLHandlingException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Writer writer = null;
try {
writer = new OutputStreamWriter(byteArrayOutputStream, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" );
} catch (IOException e) {
e.printStackTrace();
}
try {
JAXBContext JContext = JAXBContext.newInstance(Alphabet.class);
Marshaller JMarshaller = JContext.createMarshaller();
JMarshaller.marshal(theAlphabet, writer);
} catch (Throwable e) {
e.printStackTrace();
}
String theAlphabetXML = byteArrayOutputStream.toString();
return theAlphabetXML;
}
public static Alphabet parseAlphabetXML(String theAlphabetXML) throws
XMLHandlingException {
if(null == theAlphabetXML) {
return null;
}
try {
InputStream IPStream = new ByteArrayInputStream(theALphabetXML.getBytes());
JAXBContext JContext = JAXBContext.newInstance(Alphabet.class);
Unmarshaller JUnmarshaller = JContext.createUnmarshaller();
Alphabet alphabet = (Alphabet) JUnmarshaller.unmarshal(IPStream);
return alphabet;
} catch(Throwable t) {
t.printStackTrace();
}
}
My problem is that when ever I try to marshal or unmarshal I am getting the follwoing error
"javax.xml.bind.UnmarshalException: unexpected element (a:"", local:"Alphabet"). Expected elements are <{}Alphabet>"
Did I miss something? Any help is appreciated.
Thanks
Update
I followed http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html and updated my code as follows
Request and response XML
<AlphabetReq>
<a>Apple</a>
<b>Ball</b>
<c>Cat</c>
<d>Dog</d>
<e>Elephant</e>
<f>Fox</f>
</AlphabetReq>
<AlphabetResp>
<a>Apple</a>
<b>Ball</b>
<c>Cat</c>
<d>Dog</d>
<e>Elephant</e>
<f>Fox</f>
</AlphabetResp>
AlphabetReq and AlphabetResp classes
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Alph {
#XmlPath(".")
#XmlJavaTypeAdapter(AlphAdapter.class)
private LinkedHashMap<String, String> cLinkedHashMap = new
LinkedHashMap<String, String>();
#XmlPath(".")
#XmlJavaTypeAdapter(AlphAdapter.class)
private LinkedHashMap<String, String> gLinkedHashMap = new
LinkedHashMap<String, String>();
protected void put(String theKey, String theValue) {
cLinkedHashMap.put(theKey, theValue);
gLinkedHashMap.put(theKey, theValue);
}
protected String get(String theKey) {
return (String) cLinkedHashMap.get(theKey);
}
protected Set<Entry<String,String>> getCEntrySet() {
return cLinkedHashMap.entrySet();
}
protected Set<Entry<String,String>> getGEntrySet() {
return gLinkedHashMap.entrySet();
}
protected LinkedHashMap<String, String> getCLinkedHashMap() {
return cLinkedHashMap;
}
protected LinkedHashMap<String, String> getGLinkedHashMap() {
return gLinkedHashMap;
}
public String toCXML() throws XMLHandlingException {
return null;
}
public String toGXML() throws XMLHandlingException {
return null;
}
}
#XmlRootElement(name="AlphReq")
#XmlDiscriminatorValue("AlphabetReq")
#XmlAccessorType(XmlAccessType.FIELD)
public class AlphabetReq extends Alph {
public static AlphabetReq getInstance(String theAlphabetReqXML) throws
XMLHandlingException {
return XMLUtils.parseAlphabetReqXML(theAlphabetReqXML);
}
public String toCXML() throws XMLHandlingException {
return XMLUtils.getAlphabetReqXML(this);
}
}
#XmlRootElement(name="AlphResp")
#XmlDiscriminatorValue("AlphabetResp")
#XmlAccessorType(XmlAccessType.FIELD)
public class AlphabetResp extends Alph {
public static AlphabetResp getInstance(String theAlphabetRespXML) throws
XMLHandlingException {
return XMLUtils.parseAlphabetRespXML(theAlphabetRespXML);
}
public String toCXML() throws XMLHandlingException {
return XMLUtils.getAlphabetRespXML(this);
}
}
I created the following XMLUtil Methods for marshalling and unmarshalling
public static String getAlphabetReqXML(Alph theAlphabet) throws XMLHandlingException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Writer writer = null;
try {
writer = new OutputStreamWriter(byteArrayOutputStream, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" );
} catch (IOException e) {
e.printStackTrace();
}
try {
JAXBContext JContext = JAXBContext.newInstance(AlphabetReq.class);
Marshaller JMarshaller = JContext.createMarshaller();
JMarshaller.marshal(theAlphabet, writer);
} catch (Throwable e) {
e.printStackTrace();
}
String theAlphabetReqXML = byteArrayOutputStream.toString();
return theAlphabetReqXML;
}
public static AlphabetReq parseAlphabetReqXML(String theAlphabetReqXML) throws
XMLHandlingException {
if(null == theAlphabetReqXML) {
return null;
}
try {
InputStream IPStream = new ByteArrayInputStream(theAlphabetReqXML.getBytes());
JAXBContext JContext = JAXBContext.newInstance(AlphabetReq.class);
Unmarshaller JUnmarshaller = JContext.createUnmarshaller();
AlphabetReq alphabetreq = (AlphabetReq) JUnmarshaller.unmarshal(IPStream);
return alphabetreq;
} catch(Throwable t) {
t.printStackTrace();
}
}
public static String getAlphabetRespXML(Alph theAlphabet) throws XMLHandlingException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Writer writer = null;
try {
writer = new OutputStreamWriter(byteArrayOutputStream, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" );
} catch (IOException e) {
e.printStackTrace();
}
try {
JAXBContext JContext = JAXBContext.newInstance(AlphabetResp.class);
Marshaller JMarshaller = JContext.createMarshaller();
JMarshaller.marshal(theAlphabet, writer);
} catch (Throwable e) {
e.printStackTrace();
}
String theAlphabetRespXML = byteArrayOutputStream.toString();
return theAlphabetRespXML;
}
public static AlphabetResp parseAlphabetReqXML(String theAlphabetRespXML) throws
XMLHandlingException {
if(null == theAlphabetRespXML) {
return null;
}
try {
InputStream IPStream = new ByteArrayInputStream(theAlphabetRespXML.getBytes());
JAXBContext JContext = JAXBContext.newInstance(AlphabetResp.class);
Unmarshaller JUnmarshaller = JContext.createUnmarshaller();
AlphabetResp alphabetresp = (AlphabetResp) JUnmarshaller.unmarshal(IPStream);
return alphabetresp;
} catch(Throwable t) {
t.printStackTrace();
}
}
and introduced an Adapter class
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
public class AlphAdapter extends XmlAdapter<AlphAdapter.AdaptedMap, LinkedHashMap<String, String>>{
public static class AdaptedMap {
#XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
#XmlTransient
public String key;
#XmlValue
public String value;
}
#Override
public AdaptedMap marshal(LinkedHashMap<String, String> map) throws Exception {
AdaptedMap adaptedMap = new AdaptedMap();
for(Entry<String, String> entry : map.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
#Override
public LinkedHashMap<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>(adaptedEntries.size());
for(AdaptedEntry adaptedEntry : adaptedMap.entries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
}
When I run this I am not getting any values into my adaptedmap. it has keys but values as null
for ex:
key: A, value: null
key: B, value: null
key: C, value: null
key: D, value: null
key: E, value: null
key: F, value: null
Any help is appreciated.
Thanks

You can achieve this simple XML creation (that you have given) as below :
#XmlRootElement
public class Alphabet {
private String a;
private String b;
private String c;
private String d;
private String e;
private String f;
public Alphabet() {
}
public Alphabet(String a, String b, String c, String d, String e, String f) {
super();
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
public String getE() {
return e;
}
public void setE(String e) {
this.e = e;
}
public String getF() {
return f;
}
public void setF(String f) {
this.f = f;
}
}
This class is to create the xml file :
public class AlphabetToXML {
public static void main(String[] args) {
Alphabet alpha = new Alphabet("Apple", "Ball", "Cat", "Dog",
"Elephant", "Fox");
try {
String filePath = "PATH_TO_SAVE_YOUR_FILE";
File file = new File(filePath);
JAXBContext jaxbContext = JAXBContext.newInstance(Alphabet.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(alpha, file);
jaxbMarshaller.marshal(alpha, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
And this is to read your XML back to Java object :
public class XMLToAplhabet {
public static void main(String[] args) {
try {
String filePath = "XML_FILE_PATH";
File file = new File(filePath);
JAXBContext jaxbContext = JAXBContext.newInstance(Alphabet.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Alphabet aplha = (Alphabet) jaxbUnmarshaller.unmarshal(file);
System.out.println(aplha);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
I don't see any use of LinkedHashMap to create a simple XML like this.

http://java.dzone.com/articles/jaxb-and-javautilmap might be helpful. Contains different ways for doing the same task.

Related

How to initialize Multipart request for custom HttpServeletRequest

I am using springboot 2x. Our project is using a Custom HttpServeletRequest which extends HttpServletRequestWrapper and implements MultipartHttpServletRequest. Everything works fine. But when I want to work for file upload, it can't initialized Multipart request. It shows error :
java.lang.IllegalStateException: Multipart request not initialized
My question is, how can I solve this error. How Multipart request will be initialized.
I am giving all code regarding this.
public class XHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {
public XHttpServletRequest (HttpServletRequest request) {
super(request);
}
private MultiValueMap<String, MultipartFile> multipartFiles;
private String method;
#Override
public String getMethod() {
if (this.method == null) return super.getMethod();
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
private Map<String,String[]> parameters = new LinkedHashMap<String,String[]>();
public void setParameter(String name, String value) {
parameters.put(name, new String[] {value});
}
#Override
public String getParameter(String name) {
if (parameters.get(name) != null) {
return parameters.get(name)[0];
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter(name);
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<String, String[]>();
result.putAll(super.getRequest().getParameterMap());
result.putAll(parameters);
return Collections.<String, String[]>unmodifiableMap(result);
}
public Enumeration<String> getParameterNames() {
Set<String> result = new LinkedHashSet<String>(Collections.list(super.getRequest().getAttributeNames()));
result.addAll(parameters.keySet());
return new Vector<String>(result).elements();
}
public String[] getParameterValues(String name) {
if (parameters.get(name) != null) {
return parameters.get(name);
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameterValues(name);
}
#Override
public HttpServletRequest getRequest() {
return (HttpServletRequest) super.getRequest();
}
#Override
public HttpMethod getRequestMethod() {
return HttpMethod.resolve(getRequest().getMethod());
}
#Override
public HttpHeaders getRequestHeaders() {
HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, Collections.list(getHeaders(headerName)));
}
return headers;
}
#Override
public HttpHeaders getMultipartHeaders(String s) {
return null;
}
#Override
public Iterator<String> getFileNames() {
return getMultipartFiles().keySet().iterator();
}
#Override
public MultipartFile getFile(String name) {
return getMultipartFiles().getFirst(name);
}
#Override
public List<MultipartFile> getFiles(String name) {
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
if (multipartFiles != null) {
return multipartFiles;
}
else {
return Collections.emptyList();
}
}
#Override
public Map<String, MultipartFile> getFileMap() {
return getMultipartFiles().toSingleValueMap();
}
#Override
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
return getMultipartFiles();
}
#Override
public String getMultipartContentType(String s) {
return null;
}
/**
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
* To be invoked by subclasses on initialization.
*/
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
this.multipartFiles =
new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
}
/**
* Obtain the MultipartFile Map for retrieval,
* lazily initializing it if necessary.
* #see #initializeMultipart()
*/
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
if (this.multipartFiles == null) {
initializeMultipart();
}
return this.multipartFiles;
}
/**
* Lazily initialize the multipart request, if possible.
* Only called if not already eagerly initialized.
*/
protected void initializeMultipart() {
throw new IllegalStateException("Multipart request not initialized");
}
}
Another class extends XHttpServletRequest and this is instead of HttpServeletRequest in our project. The following code:
public class YHttpRequest extends MutableHttpServletRequest {
private ByteArrayOutputStream cachedBytes;
public YHttpRequest(HttpServletRequest request) {
super(request);
}
#Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
#Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times. For
* convenience, I use apache.commons IOUtils
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
public List<Map<String, Object>> getListData() throws RequestException {
List<Map<String, Object>> data = new ArrayList<>();
try {
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(this.getInputStream(), new TypeReference<ArrayList<LinkedHashMap>>(){});
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
private Object cachedData = null;
public Object getRawData() throws RequestException {
Object data = new LinkedHashMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
// data = mapper.readValue(this.getInputStream());
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<HashMap>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<List<HashMap>>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
public Object getData() throws RequestException {
if (this.cachedData == null) {
this.cachedData = this.getRawData();
}
return this.cachedData;
}
/* An inputstream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
#Override
public boolean isFinished() {
return input.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
// throw new IOException("zubair says: Method not implemented in Cached Servlet Input Stream class");
}
#Override
public int read() throws IOException {
return input.read();
}
}
// Storage for Path variable
private Map<String, Object> pathVariableMap = null;
public Map<String, Object> getPathVariableMap() {
if (this.pathVariableMap == null) {
this.pathVariableMap = new LinkedHashMap<>();
this.pathVariableMap.putAll((Map<? extends String, ?>) this.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
}
return this.pathVariableMap;
}
public Object getPathVariable(String key) {
return this.getPathVariableMap().get(key);
}
public FurinaHttpRequest setPathVariable(String key, Object value) {
this.getPathVariableMap().put(key, value);
return this;
}
public FurinaHttpRequest clearPathVariableMap() {
this.getPathVariableMap().clear();
return this;
}
}
The controller code:
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
This will work
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = new StandardMultipartHttpServletRequest(request);
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}

Get single field from JSON using Jackson

Given an arbitrary JSON I would like to get value of a single field contentType. How to do it with Jackson?
{
contentType: "foo",
fooField1: ...
}
{
contentType: "bar",
barArray: [...]
}
Related
How to find specified name and its value in JSON-string from Java? (GSON)
Using gson to deserialize specific JSON field of an object (GSON)
The Jackson Way
Considering that you don't have a POJO describing your data structure, you could simply do:
final String json = "{\"contentType\": \"foo\", \"fooField1\": ... }";
final ObjectNode node = new ObjectMapper().readValue(json, ObjectNode.class);
// ^
// actually, try and *reuse* a single instance of ObjectMapper
if (node.has("contentType")) {
System.out.println("contentType: " + node.get("contentType"));
}
Addressing concerns in the comments section
If, however, you wish to not consume the entire source String, but simply access a specific property whose path you know, you'll have to write it yourself, leveraging a Tokeniser.
Actually, it's the weekend and I got time on my hands, so I could give you a head start: here's a basic one! It can run in strict mode and spew out sensible error messages, or be lenient and return Optional.empty when the request couldn't be fulfilled.
public static class JSONPath {
protected static final JsonFactory JSON_FACTORY = new JsonFactory();
private final List<JSONKey> keys;
public JSONPath(final String from) {
this.keys = Arrays.stream((from.startsWith("[") ? from : String.valueOf("." + from))
.split("(?=\\[|\\]|\\.)"))
.filter(x -> !"]".equals(x))
.map(JSONKey::new)
.collect(Collectors.toList());
}
public Optional<String> getWithin(final String json) throws IOException {
return this.getWithin(json, false);
}
public Optional<String> getWithin(final String json, final boolean strict) throws IOException {
try (final InputStream stream = new StringInputStream(json)) {
return this.getWithin(stream, strict);
}
}
public Optional<String> getWithin(final InputStream json) throws IOException {
return this.getWithin(json, false);
}
public Optional<String> getWithin(final InputStream json, final boolean strict) throws IOException {
return getValueAt(JSON_FACTORY.createParser(json), 0, strict);
}
protected Optional<String> getValueAt(final JsonParser parser, final int idx, final boolean strict) throws IOException {
try {
if (parser.isClosed()) {
return Optional.empty();
}
if (idx >= this.keys.size()) {
parser.nextToken();
if (null == parser.getValueAsString()) {
throw new JSONPathException("The selected node is not a leaf");
}
return Optional.of(parser.getValueAsString());
}
this.keys.get(idx).advanceCursor(parser);
return getValueAt(parser, idx + 1, strict);
} catch (final JSONPathException e) {
if (strict) {
throw (null == e.getCause() ? new JSONPathException(e.getMessage() + String.format(", at path: '%s'", this.toString(idx)), e) : e);
}
return Optional.empty();
}
}
#Override
public String toString() {
return ((Function<String, String>) x -> x.startsWith(".") ? x.substring(1) : x)
.apply(this.keys.stream().map(JSONKey::toString).collect(Collectors.joining()));
}
private String toString(final int idx) {
return ((Function<String, String>) x -> x.startsWith(".") ? x.substring(1) : x)
.apply(this.keys.subList(0, idx).stream().map(JSONKey::toString).collect(Collectors.joining()));
}
#SuppressWarnings("serial")
public static class JSONPathException extends RuntimeException {
public JSONPathException() {
super();
}
public JSONPathException(final String message) {
super(message);
}
public JSONPathException(final String message, final Throwable cause) {
super(message, cause);
}
public JSONPathException(final Throwable cause) {
super(cause);
}
}
private static class JSONKey {
private final String key;
private final JsonToken startToken;
public JSONKey(final String str) {
this(str.substring(1), str.startsWith("[") ? JsonToken.START_ARRAY : JsonToken.START_OBJECT);
}
private JSONKey(final String key, final JsonToken startToken) {
this.key = key;
this.startToken = startToken;
}
/**
* Advances the cursor until finding the current {#link JSONKey}, or
* having consumed the entirety of the current JSON Object or Array.
*/
public void advanceCursor(final JsonParser parser) throws IOException {
final JsonToken token = parser.nextToken();
if (!this.startToken.equals(token)) {
throw new JSONPathException(String.format("Expected token of type '%s', got: '%s'", this.startToken, token));
}
if (JsonToken.START_ARRAY.equals(this.startToken)) {
// Moving cursor within a JSON Array
for (int i = 0; i != Integer.valueOf(this.key).intValue(); i++) {
JSONKey.skipToNext(parser);
}
} else {
// Moving cursor in a JSON Object
String name;
for (parser.nextToken(), name = parser.getCurrentName(); !this.key.equals(name); parser.nextToken(), name = parser.getCurrentName()) {
JSONKey.skipToNext(parser);
}
}
}
/**
* Advances the cursor to the next entry in the current JSON Object
* or Array.
*/
private static void skipToNext(final JsonParser parser) throws IOException {
final JsonToken token = parser.nextToken();
if (JsonToken.START_ARRAY.equals(token) || JsonToken.START_OBJECT.equals(token) || JsonToken.FIELD_NAME.equals(token)) {
skipToNextImpl(parser, 1);
} else if (JsonToken.END_ARRAY.equals(token) || JsonToken.END_OBJECT.equals(token)) {
throw new JSONPathException("Could not find requested key");
}
}
/**
* Recursively consumes whatever is next until getting back to the
* same depth level.
*/
private static void skipToNextImpl(final JsonParser parser, final int depth) throws IOException {
if (depth == 0) {
return;
}
final JsonToken token = parser.nextToken();
if (JsonToken.START_ARRAY.equals(token) || JsonToken.START_OBJECT.equals(token) || JsonToken.FIELD_NAME.equals(token)) {
skipToNextImpl(parser, depth + 1);
} else {
skipToNextImpl(parser, depth - 1);
}
}
#Override
public String toString() {
return String.format(this.startToken.equals(JsonToken.START_ARRAY) ? "[%s]" : ".%s", this.key);
}
}
}
Assuming the following JSON content:
{
"people": [{
"name": "Eric",
"age": 28
}, {
"name": "Karin",
"age": 26
}],
"company": {
"name": "Elm Farm",
"address": "3756 Preston Street Wichita, KS 67213",
"phone": "857-778-1265"
}
}
... you could use my JSONPath class as follows:
final String json = "{\"people\":[],\"company\":{}}"; // refer to JSON above
System.out.println(new JSONPath("people[0].name").getWithin(json)); // Optional[Eric]
System.out.println(new JSONPath("people[1].name").getWithin(json)); // Optional[Karin]
System.out.println(new JSONPath("people[2].name").getWithin(json)); // Optional.empty
System.out.println(new JSONPath("people[0].age").getWithin(json)); // Optional[28]
System.out.println(new JSONPath("company").getWithin(json)); // Optional.empty
System.out.println(new JSONPath("company.name").getWithin(json)); // Optional[Elm Farm]
Keep in mind that it's basic. It doesn't coerce data types (every value it returns is a String) and only returns leaf nodes.
Actual test case
It handles InputStreams, so you can test it against some giant JSON document and see that it's much faster than it would take your browser to download and display its contents:
System.out.println(new JSONPath("info.contact.email")
.getWithin(new URL("http://test-api.rescuegroups.org/v5/public/swagger.php").openStream()));
// Optional[support#rescuegroups.org]
Quick test
Note I'm not re-using any already existing JSONPath or ObjectMapper so the results are inaccurate -- this is just a very rough comparison anyways:
public static Long time(final Callable<?> r) throws Exception {
final long start = System.currentTimeMillis();
r.call();
return Long.valueOf(System.currentTimeMillis() - start);
}
public static void main(final String[] args) throws Exception {
final URL url = new URL("http://test-api.rescuegroups.org/v5/public/swagger.php");
System.out.println(String.format( "%dms to get 'info.contact.email' with JSONPath",
time(() -> new JSONPath("info.contact.email").getWithin(url.openStream()))));
System.out.println(String.format( "%dms to just download the entire document otherwise",
time(() -> new Scanner(url.openStream()).useDelimiter("\\A").next())));
System.out.println(String.format( "%dms to bluntly map it entirely with Jackson and access a specific field",
time(() -> new ObjectMapper()
.readValue(url.openStream(), ObjectNode.class)
.get("info").get("contact").get("email"))));
}
378ms to get 'info.contact.email' with JSONPath
756ms to just download the entire document otherwise
896ms to bluntly map it entirely with Jackson and access a specific field
Just want to update for 2019. I found the following easiest to impl:
//json can be file or String
JsonNode parent= new ObjectMapper().readTree(json);
String content = parent.path("contentType").asText();
I would suggest to use path instead of get as get throws a NPE, where path returns with a default 0 or "", which is safer to work with if setting up the parsing correctly for 1st time.
My $0.02
If you are using JSON jars in your application then the following code snippet is useful:
String json = "{\"contentType\": \"foo\", \"fooField1\": ... }";
JSONObject jsonObject = new JSONObject(json);
System.out.println(jsonObject.getString("contentType"));
and if you are using Gson jars then the same code will look like following:
Gson gson = new GsonBuilder().create();
Map jsonMap = gson.fromJson(json, Map.class);
System.out.println(jsonMap.get("contentType"));
Another way is:
String json = "{\"contentType\": \"foo\", \"fooField1\": ... }";
JsonNode parent= new ObjectMapper().readTree(json);
String content = parent.get("contentType").asText();
I faced this issue when I decided to use Jackson as the json library for a project I worked on; mainly for its speed. I was already used to using org.json and Gson for my projects.
I quickly found out though that many tasks that were trivial in org.json and Gson were not so straightforward in Jackson
So I wrote the following classes to make things easier for me.
The classes below will allow you to use Jackson as easily as you would the simple org.json library, while still retaining the power and speed of Jackson
I wrote the whole thing in a few hours, so feel free to debug and suit the code to your own purposes.
Note that JSONObject/JSONArray below will do exactly what the OP wants.
The first is JSONObject which has similar methods to org.json.JSONObject; but at heart runs Jackson code to build JSON and parse json strings.
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author GBEMIRO JIBOYE <gbenroscience#gmail.com>
*/
public class JSONObject {
ObjectNode parseNode;
public JSONObject() {
this.parseNode = JsonNodeFactory.instance.objectNode(); // initializing
}
public JSONObject(String json) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
try {
this.parseNode = mapper.readValue(json, ObjectNode.class);
} catch (JsonProcessingException ex) {
Logger.getLogger(JSONObject.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void put(String key, String value) {
parseNode.put("key", value); // building
}
public void put(String key, boolean value) {
parseNode.put("key", value); // building
}
public void put(String key, int value) {
parseNode.put("key", value); // building
}
public void put(String key, short value) {
parseNode.put("key", value); // building
}
public void put(String key, float value) {
parseNode.put("key", value); // building
}
public void put(String key, long value) {
parseNode.put("key", value); // building
}
public void put(String key, double value) {
parseNode.put("key", value); // building
}
public void put(String key, byte[] value) {
parseNode.put("key", value); // building
}
public void put(String key, BigInteger value) {
parseNode.put("key", value); // building
}
public void put(String key, BigDecimal value) {
parseNode.put("key", value); // building
}
public void put(String key, Object[] value) {
ArrayNode anode = parseNode.putArray(key);
for (Object o : value) {
anode.addPOJO(o); // building
}
}
public void put(String key, JSONObject value) {
parseNode.set(key, value.parseNode);
}
public void put(String key, Object value) {
parseNode.putPOJO(key, value);
}
public static class Parser<T> {
public T decode(String json, Class clazz) {
try {
return new Converter<T>().fromJsonString(json, clazz);
} catch (IOException ex) {
Logger.getLogger(JSONObject.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
public int optInt(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null ? nod.asInt(0) : 0;
}
return 0;
}
public long optLong(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null ? nod.asLong(0) : 0;
}
return 0;
}
public double optDouble(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null ? nod.asDouble(0) : 0;
}
return 0;
}
public boolean optBoolean(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null ? nod.asBoolean(false) : false;
}
return false;
}
public double optFloat(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null && nod.isFloat() ? nod.floatValue() : 0;
}
return 0;
}
public short optShort(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null && nod.isShort() ? nod.shortValue() : 0;
}
return 0;
}
public byte optByte(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return nod != null && nod.isShort() ? (byte) nod.asInt(0) : 0;
}
return 0;
}
public JSONObject optJSONObject(String key) {
if (parseNode != null) {
if (parseNode.has(key)) {
ObjectNode nod = parseNode.with(key);
JSONObject obj = new JSONObject();
obj.parseNode = nod;
return obj;
}
}
return new JSONObject();
}
public JSONArray optJSONArray(String key) {
if (parseNode != null) {
if (parseNode.has(key)) {
ArrayNode nod = parseNode.withArray(key);
JSONArray obj = new JSONArray();
if (nod != null) {
obj.parseNode = nod;
return obj;
}
}
}
return new JSONArray();
}
public String optString(String key) {
if (parseNode != null) {
JsonNode nod = parseNode.get(key);
return parseNode != null && nod.isTextual() ? nod.asText("") : "";
}
return "";
}
#Override
public String toString() {
return parseNode.toString();
}
public String toCuteString() {
return parseNode.toPrettyString();
}
}
Here is the code for the JSONArray equivalent that works like org.json.JSONArray; but uses Jackson code.
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
*
* #author GBEMIRO JIBOYE <gbenroscience#gmail.com>
*/
public class JSONArray {
protected ArrayNode parseNode;
public JSONArray() {
this.parseNode = JsonNodeFactory.instance.arrayNode(); // initializing
}
public JSONArray(String json) throws JsonProcessingException{
ObjectMapper mapper = new ObjectMapper();
this.parseNode = mapper.readValue(json, ArrayNode.class);
}
public void putByte(byte val) {
parseNode.add(val);
}
public void putShort(short val) {
parseNode.add(val);
}
public void put(int val) {
parseNode.add(val);
}
public void put(long val) {
parseNode.add(val);
}
public void pu(float val) {
parseNode.add(val);
}
public void put(double val) {
parseNode.add(val);
}
public void put(String val) {
parseNode.add(val);
}
public void put(byte[] val) {
parseNode.add(val);
}
public void put(BigDecimal val) {
parseNode.add(val);
}
public void put(BigInteger val) {
parseNode.add(val);
}
public void put(Object val) {
parseNode.addPOJO(val);
}
public void put(int index, JSONArray value) {
parseNode.set(index, value.parseNode);
}
public void put(int index, JSONObject value) {
parseNode.set(index, value.parseNode);
}
public String optString(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null ? nod.asText("") : "";
}
return "";
}
public int optInt(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null ? nod.asInt(0) : 0;
}
return 0;
}
public long optLong(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null ? nod.asLong(0) : 0;
}
return 0;
}
public double optDouble(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null ? nod.asDouble(0) : 0;
}
return 0;
}
public boolean optBoolean(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null ? nod.asBoolean(false) : false;
}
return false;
}
public double optFloat(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null && nod.isFloat() ? nod.floatValue() : 0;
}
return 0;
}
public short optShort(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null && nod.isShort() ? nod.shortValue() : 0;
}
return 0;
}
public byte optByte(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
return nod != null && nod.isShort() ? (byte) nod.asInt(0) : 0;
}
return 0;
}
public JSONObject optJSONObject(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
if(nod != null){
if(nod.isObject()){
ObjectNode obn = (ObjectNode) nod;
JSONObject obj = new JSONObject();
obj.parseNode = obn;
return obj;
}
}
}
return new JSONObject();
}
public JSONArray optJSONArray(int index) {
if (parseNode != null) {
JsonNode nod = parseNode.get(index);
if(nod != null){
if(nod.isArray()){
ArrayNode anode = (ArrayNode) nod;
JSONArray obj = new JSONArray();
obj.parseNode = anode;
return obj;
}
}
}
return new JSONArray();
}
#Override
public String toString() {
return parseNode.toString();
}
public String toCuteString() {
return parseNode.toPrettyString();
}
}
Finally for a one size-fits-all-most-likely for encoding and decoding your Java classes to JSON, I added this simple class:
/**
*
* #author GBEMIRO JIBOYE <gbenroscience#gmail.com>
*/
public class Converter<T> {
// Serialize/deserialize helpers
private Class clazz;
public Converter() {}
public T fromJsonString(String json , Class clazz) throws IOException {
this.clazz = clazz;
return getObjectReader().readValue(json);
}
public String toJsonString(T obj) throws JsonProcessingException {
this.clazz = obj.getClass();
return getObjectWriter().writeValueAsString(obj);
}
private ObjectReader requestReader;
private ObjectWriter requestWriter;
private void instantiateMapper() {
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
requestReader = mapper.readerFor(clazz);
requestWriter = mapper.writerFor(clazz);
}
private ObjectReader getObjectReader() {
if (requestReader == null) {
instantiateMapper();
}
return requestReader;
}
private ObjectWriter getObjectWriter() {
if (requestWriter == null) {
instantiateMapper();
}
return requestWriter;
}
}
Now to taste(test) the sauce(code), use the following methods:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author GBEMIRO JIBOYE <gbenroscience#gmail.com>
*/
public class SimplerJacksonTest {
static class Credentials {
private String userName;
private String uid;
private String password;
private long createdAt;
public Credentials() {
}
public Credentials(String userName, String uid, String password, long createdAt) {
this.userName = userName;
this.uid = uid;
this.password = password;
this.createdAt = createdAt;
}
#JsonProperty("userName")
public String getUserName() {
return userName;
}
#JsonProperty("userName")
public void setUserName(String userName) {
this.userName = userName;
}
#JsonProperty("uid")
public String getUid() {
return uid;
}
#JsonProperty("uid")
public void setUid(String uid) {
this.uid = uid;
}
#JsonProperty("password")
public String getPassword() {
return password;
}
#JsonProperty("password")
public void setPassword(String password) {
this.password = password;
}
#JsonProperty("createdAt")
public long getCreatedAt() {
return createdAt;
}
#JsonProperty("createdAt")
public void setCreatedAt(long createdAt) {
this.createdAt = createdAt;
}
public String encode() {
try {
return new Converter<Credentials>().toJsonString(this);
} catch (JsonProcessingException ex) {
Logger.getLogger(Credentials.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public Credentials decode(String jsonData) {
try {
return new Converter<Credentials>().fromJsonString(jsonData, Credentials.class);
} catch (Exception ex) {
Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
public static JSONObject testJSONObjectBuild() {
JSONObject obj = new JSONObject();
Credentials cred = new Credentials("Adesina", "01eab26bwkwjbak2vngxh9y3q6", "xxxxxx1234", System.currentTimeMillis());
String arr[] = new String[]{"Boy", "Girl", "Man", "Woman"};
int nums[] = new int[]{0, 1, 2, 3, 4, 5};
obj.put("creds", cred);
obj.put("pronouns", arr);
obj.put("creds", cred);
obj.put("nums", nums);
System.out.println("json-coding: " + obj.toCuteString());
return obj;
}
public static void testJSONObjectParse(String json) {
JSONObject obj;
try {
obj = new JSONObject(json);
JSONObject credsObj = obj.optJSONObject("creds");
String userName = credsObj.optString("userName");
String uid = credsObj.optString("uid");
String password = credsObj.optString("password");
long createdAt = credsObj.optLong("createdAt");
System.out.println("<<---Parse Results--->>");
System.out.println("userName = " + userName);
System.out.println("uid = " + uid);
System.out.println("password = " + password);
System.out.println("createdAt = " + createdAt);
} catch (JsonProcessingException ex) {
Logger.getLogger(JSONObject.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static JSONArray testJSONArrayBuild() {
JSONArray array = new JSONArray();
array.put(new Credentials("Lawani", "001uadywdbs", "ampouehehu", System.currentTimeMillis()));
array.put("12");
array.put(98);
array.put(Math.PI);
array.put("Good scores!");
System.out.println("See the built array: "+array.toCuteString());
return array;
}
public static void testJSONArrayParse(String json) {
try {
JSONArray array = new JSONArray(json);
JSONObject credsObj = array.optJSONObject(0);
//Parse credentials in index 0
String userName = credsObj.optString("userName");
String uid = credsObj.optString("uid");
String password = credsObj.optString("password");
long createdAt = credsObj.optLong("createdAt");
//Now return to the main array and parse other entries
String twelve = array.optString(1);
int ninety = array.optInt(2);
double pi = array.optDouble(3);
String scoreNews = array.optString(4);
System.out.println("Parse Results");
System.out.println("userName = " + userName);
System.out.println("uid = " + uid);
System.out.println("password = " + password);
System.out.println("createdAt = " + createdAt);
System.out.println("Parse Results");
System.out.println("index 1 = " + twelve);
System.out.println("index 2 = " + ninety);
System.out.println("index 3 = " + pi);
System.out.println("index 4 = " + scoreNews);
} catch (JsonProcessingException ex) {
Logger.getLogger(JSONObject.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static String testCredentialsEncode(){
Credentials cred = new Credentials("Olaoluwa", "01eab26bwkwjbak2vngxh9y3q6", "xxxxxx1234", System.currentTimeMillis());
String encoded = cred.encode();
System.out.println("encoded credentials = "+encoded);
return encoded;
}
public static Credentials testCredentialsDecode(String json){
Credentials cred = new Credentials().decode(json);
System.out.println("encoded credentials = "+cred.encode());
return cred;
}
public static void main(String[] args) {
JSONObject jo = testJSONObjectBuild();
testJSONObjectParse(jo.toString());
JSONArray ja = testJSONArrayBuild();
testJSONArrayParse(ja.toString());
String credsJSON = testCredentialsEncode();
testCredentialsDecode(credsJSON);
}
}
To get the source code in a place, instead of having to copy the one here, see:
the code on Github

get value from xml in method with specific parameters JAVA

I'm newbie in XML parsing and try to understand JAXB. Have the following task:
Implemented the following method, to got the személy object by id parameter,but it returns null:
public Személy getSzemélyById(String id) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Személy.class);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
XMLReader xmlReader = spf.newSAXParser().getXMLReader();
InputSource inputSource;
inputSource = new InputSource(new FileReader("C:\\Users\\zbocskay.TS-EU\\Documents\\NetBeansProjects\\prt2014levzh\\people.xml"));
SAXSource source = new SAXSource(xmlReader, inputSource);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Személy személy = (Személy) unmarshaller.unmarshal(source);
System.out.println(személy.toString());
return new Személy(személy.getId(), személy.getVezetéknév(), személy.getKeresztnév(), személy.getÉletkor(), személy.getCím(), személy.státusz.DIÁK);
} catch (JAXBException e) {
} catch (FileNotFoundException | ParserConfigurationException ex) {
Logger.getLogger(SzemélyDAOImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SAXNotRecognizedException ex) {
Logger.getLogger(SzemélyDAOImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SAXNotSupportedException ex) {
Logger.getLogger(SzemélyDAOImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SAXException ex) {
Logger.getLogger(SzemélyDAOImpl.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
Here is Személy Class:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Személy {
public enum Státusz {
FELNŐTT, DIÁK, NYUGDÍJAS, GYERMEK
}
#XmlElement
protected String id;
#XmlElement
protected String vezetéknév;
#XmlElement
protected String keresztnév;
protected Integer életkor;
#XmlElement
protected String cím;
protected Státusz státusz;
public Személy(String id) {
super();
this.id = id;
}
public void setÉletkor(Integer életkor) {
this.életkor = életkor;
}
public String getVezetéknév() {
return vezetéknév;
}
public void setVezetéknév(String vezetéknév) {
this.vezetéknév = vezetéknév;
}
public String getKeresztnév() {
return keresztnév;
}
public void setKeresztnév(String keresztnév) {
this.keresztnév = keresztnév;
}
public String getCím() {
return cím;
}
public void setCím(String cím) {
this.cím = cím;
}
public String getId() {
return id;
}
public Személy(String id, String vezetéknév, String keresztnév,
Integer életkor, String cím, Státusz státusz) {
this(id);
this.vezetéknév = vezetéknév;
this.keresztnév = keresztnév;
this.életkor = életkor;
this.cím = cím;
this.státusz = státusz;
}
public Személy(String id, String vezetéknév, String keresztnév,
String születésiDátum, String cím, String diákigazolványszám,
Státusz státusz) throws ParseException {
this(id);
this.vezetéknév = vezetéknév;
this.keresztnév = keresztnév;
this.életkor = meghatározÉletkort(születésiDátum);
this.cím = cím;
this.státusz = státusz;
}
public Integer getÉletkor() {
return életkor;
}
#Override
public String toString() {
return "Személy [id=" + id + ", vezetéknév=" + vezetéknév
+ ", keresztnév=" + keresztnév + ", életkor=" + életkor
+ ", cím=" + cím + ", státusz=" + státusz + "]";
}
}
And people.xml file with data:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE személyek SYSTEM "people.dtd">
<személyek>
<személy id="micimacko">
<vezetéknév>Mici</vezetéknév>
<keresztnév>Mackó</keresztnév>
<születésidátum>1921.08.21</születésidátum>
<cím>Százholdas Pagony</cím>
<fotó>http://upload.wikimedia.org/wikipedia/en/1/10/Winniethepooh.png
</fotó>
</személy>
</személyek>
Running in the main class by the following:
public static void main(String args[]) {
SzemélyDAO ddd = new SzemélyDAOImpl();
System.out.println(ddd.getSzemélyById("micimacko"));
}
Could anybody help me, what am I doing wrong?Thanks.
As the exception states you need to add a no-arg constructor to your Személy class. This means a constructor that doesn't take any parameters. Currently the class has a single constructor that takes a String. Adding the following would work:
private Személy() {
}

Java Reflection/BeanUtils issue

I'm trying to populate a bean with some table driven attribute:value pairs. I retrieve them from a MySQL table, and populate a hashmap just fine. I iterate through the hashmap, and if I use PropertyUtils.setProperty() I get a "Class does not have setter for *" error. If I use BeanUtils.setProperty() the bean never gets populated. Here's the sample:
public class DBDrivenPayloadHandler extends GDE{
DbDrivenPayloadHandlerBean bean;
#SuppressWarnings("rawtypes")
public void populateBean() throws Exception {
ITransaction trans = new MySQLTransaction();
IAdapterDataMapDAO adapterDataMap = new MySQLAdapterDataMapDAO();
adapterDataMap.setTransaction(trans);
HashMap<String, String> values = adapterDataMap.getHashMap(super.getCurrentAccountId());
//hashmap gets populated correctly with correct variable names and values != "-1";
DbDrivenPayloadHandlerBean bean = new DbDrivenPayloadHandlerBean();
//We have a bean with all the intialized variable values
Iterator it = values.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
try {
PropertyUtils.setProperty(bean, (String) entry.getKey(), entry.getValue());
//PropertyUtils will give a setter not found error. BeanUtils never sets the values.
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void getInfo(String fileName) {
try {
populateBean();
} catch (Exception e) {
e.printStackTrace();
}
APPTS_FULLNAME_POS = bean.getAPPTS_FULLNAME_POS();
APPTS_DATETIME_POS = bean.getAPPTS_DATETIME_POS();
//Both still -1;
super.getInfo(filename);
}
And here's the Bean (or at least some of it):
public class DbDrivenPayloadHandlerBean {
int APPTS_FULLNAME_POS = -1;
int APPTS_DATETIME_POS = -1;
public DbDrivenPayloadHandlerBean() {
super();
}
public int getAPPTS_FULLNAME_POS() {
return APPTS_FULLNAME_POS;
}
public void setAPPTS_FULLNAME_POS(String APPTS_FULLNAME_POS) {
this.APPTS_FULLNAME_POS = Integer.parseInt(APPTS_FULLNAME_POS);
}
public int getAPPTS_DATETIME_POS() {
return APPTS_DATETIME_POS;
}
public void setAPPTS_DATETIME_POS(String APPTS_DATETIME_POS) {
this.APPTS_DATETIME_POS = Integer.parseInt(APPTS_DATETIME_POS);
}
Sorry guys, BeanUtils does the trick. I just don't want to be allowing setters that take Strings. I guess reflection does the casting for you. Apologies.
Solution as stated above: don't try to cast for BeanUtils.
public class DBDrivenPayloadHandler extends GDE{
DbDrivenPayloadHandlerBean bean;
#SuppressWarnings("rawtypes")
public void populateBean() throws Exception {
ITransaction trans = new MySQLTransaction();
IAdapterDataMapDAO adapterDataMap = new MySQLAdapterDataMapDAO();
adapterDataMap.setTransaction(trans);
HashMap<String, String> values = adapterDataMap.getHashMap(super.getCurrentAccountId());
this.bean = new DbDrivenPayloadHandlerBean();
Iterator it = values.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
try {
BeanUtils.setProperty(bean, (String) entry.getKey(), entry.getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void getInfo(String fileName) {
try {
populateBean();
} catch (Exception e) {
e.printStackTrace();
}
APPTS_FULLNAME_POS = bean.getAPPTS_FULLNAME_POS();
APPTS_DATETIME_POS = bean.getAPPTS_DATETIME_POS();
//Both still -1;
super.getInfo(filename);
}
Bean
public class DbDrivenPayloadHandlerBean {
int APPTS_FULLNAME_POS = -1;
int APPTS_DATETIME_POS = -1;
public DbDrivenPayloadHandlerBean() {
super();
}
public int getAPPTS_FULLNAME_POS() {
return APPTS_FULLNAME_POS;
}
public void setAPPTS_FULLNAME_POS(int APPTS_FULLNAME_POS) {
this.APPTS_FULLNAME_POS = APPTS_FULLNAME_POS;
}
public int getAPPTS_DATETIME_POS() {
return APPTS_DATETIME_POS;
}
public void setAPPTS_DATETIME_POS(String APPTS_DATETIME_POS) {
this.APPTS_DATETIME_POS = APPTS_DATETIME_POS;
}

How to set keys and values of a hashmap as tags and values of a xml file

I followed http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html and wrote my code as follows
Request and response XML
<AlphabetReq>
<a>Apple</a>
<b>Ball</b>
<c>Cat</c>
<d>Dog</d>
<e>Elephant</e>
<f>Fox</f>
</AlphabetReq>
<AlphabetResp>
<a>Apple</a>
<b>Ball</b>
<c>Cat</c>
<d>Dog</d>
<e>Elephant</e>
<f>Fox</f>
</AlphabetResp>
AlphabetReq and AlphabetResp classes
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Alph {
#XmlPath(".")
#XmlJavaTypeAdapter(AlphAdapter.class)
private LinkedHashMap<String, String> cLinkedHashMap = new
LinkedHashMap<String, String>();
#XmlPath(".")
#XmlJavaTypeAdapter(AlphAdapter.class)
private LinkedHashMap<String, String> gLinkedHashMap = new
LinkedHashMap<String, String>();
protected void put(String theKey, String theValue) {
cLinkedHashMap.put(theKey, theValue);
gLinkedHashMap.put(theKey, theValue);
}
protected String get(String theKey) {
return (String) cLinkedHashMap.get(theKey);
}
protected Set<Entry<String,String>> getCEntrySet() {
return cLinkedHashMap.entrySet();
}
protected Set<Entry<String,String>> getGEntrySet() {
return gLinkedHashMap.entrySet();
}
protected LinkedHashMap<String, String> getCLinkedHashMap() {
return cLinkedHashMap;
}
protected LinkedHashMap<String, String> getGLinkedHashMap() {
return gLinkedHashMap;
}
public String toCXML() throws XMLHandlingException {
return null;
}
public String toGXML() throws XMLHandlingException {
return null;
}
}
#XmlRootElement(name="AlphReq")
#XmlDiscriminatorValue("AlphabetReq")
#XmlAccessorType(XmlAccessType.FIELD)
public class AlphabetReq extends Alph {
public static AlphabetReq getInstance(String theAlphabetReqXML) throws
XMLHandlingException {
return XMLUtils.parseAlphabetReqXML(theAlphabetReqXML);
}
public String toCXML() throws XMLHandlingException {
return XMLUtils.getAlphabetReqXML(this);
}
}
#XmlRootElement(name="AlphResp")
#XmlDiscriminatorValue("AlphabetResp")
#XmlAccessorType(XmlAccessType.FIELD)
public class AlphabetResp extends Alph {
public static AlphabetResp getInstance(String theAlphabetRespXML) throws
XMLHandlingException {
return XMLUtils.parseAlphabetRespXML(theAlphabetRespXML);
}
public String toCXML() throws XMLHandlingException {
return XMLUtils.getAlphabetRespXML(this);
}
}
I created the following XMLUtil Methods for marshalling and unmarshalling
public static String getAlphabetReqXML(Alph theAlphabet) throws XMLHandlingException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Writer writer = null;
try {
writer = new OutputStreamWriter(byteArrayOutputStream, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" );
} catch (IOException e) {
e.printStackTrace();
}
try {
JAXBContext JContext = JAXBContext.newInstance(AlphabetReq.class);
Marshaller JMarshaller = JContext.createMarshaller();
JMarshaller.marshal(theAlphabet, writer);
} catch (Throwable e) {
e.printStackTrace();
}
String theAlphabetReqXML = byteArrayOutputStream.toString();
return theAlphabetReqXML;
}
public static AlphabetReq parseAlphabetReqXML(String theAlphabetReqXML) throws
XMLHandlingException {
if(null == theAlphabetReqXML) {
return null;
}
try {
InputStream IPStream = new ByteArrayInputStream(theAlphabetReqXML.getBytes());
JAXBContext JContext = JAXBContext.newInstance(AlphabetReq.class);
Unmarshaller JUnmarshaller = JContext.createUnmarshaller();
AlphabetReq alphabetreq = (AlphabetReq) JUnmarshaller.unmarshal(IPStream);
return alphabetreq;
} catch(Throwable t) {
t.printStackTrace();
}
}
public static String getAlphabetRespXML(Alph theAlphabet) throws XMLHandlingException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Writer writer = null;
try {
writer = new OutputStreamWriter(byteArrayOutputStream, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" );
} catch (IOException e) {
e.printStackTrace();
}
try {
JAXBContext JContext = JAXBContext.newInstance(AlphabetResp.class);
Marshaller JMarshaller = JContext.createMarshaller();
JMarshaller.marshal(theAlphabet, writer);
} catch (Throwable e) {
e.printStackTrace();
}
String theAlphabetRespXML = byteArrayOutputStream.toString();
return theAlphabetRespXML;
}
public static AlphabetResp parseAlphabetReqXML(String theAlphabetRespXML) throws
XMLHandlingException {
if(null == theAlphabetRespXML) {
return null;
}
try {
InputStream IPStream = new ByteArrayInputStream(theAlphabetRespXML.getBytes());
JAXBContext JContext = JAXBContext.newInstance(AlphabetResp.class);
Unmarshaller JUnmarshaller = JContext.createUnmarshaller();
AlphabetResp alphabetresp = (AlphabetResp) JUnmarshaller.unmarshal(IPStream);
return alphabetresp;
} catch(Throwable t) {
t.printStackTrace();
}
}
and introduced an Adapter class
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
public class AlphAdapter extends XmlAdapter<AlphAdapter.AdaptedMap, LinkedHashMap<String, String>>{
public static class AdaptedMap {
#XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
#XmlTransient
public String key;
#XmlValue
public String value;
}
#Override
public AdaptedMap marshal(LinkedHashMap<String, String> map) throws Exception {
AdaptedMap adaptedMap = new AdaptedMap();
for(Entry<String, String> entry : map.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
#Override
public LinkedHashMap<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>(adaptedEntries.size());
for(AdaptedEntry adaptedEntry : adaptedMap.entries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
}
When I run this I am not getting any values into my adaptedmap. it has keys but values as null
for ex:
key: A, value: null
key: B, value: null
key: C, value: null
key: D, value: null
key: E, value: null
key: F, value: null
Any help is appreciated.
Thanks
TL;DR
The problem is you are trying to employ the use element name as key trick for two maps at the same level. This is causing your problem.
#XmlPath(".")
#XmlJavaTypeAdapter(AlphAdapter.class)
private LinkedHashMap<String, String> cLinkedHashMap = new
LinkedHashMap<String, String>();
#XmlPath(".")
#XmlJavaTypeAdapter(AlphAdapter.class)
private LinkedHashMap<String, String> gLinkedHashMap = new
LinkedHashMap<String, String>();
Below is how your stuff currently works
Demo Code
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(AlphabetReq.class, AlphabetResp.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18741690/input.xml");
AlphabetReq ar = (AlphabetReq) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(ar, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<AlphReq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AlphabetReq">
<a/>
<b/>
<c/>
<d/>
<e/>
<f/>
<a>Apple</a>
<b>Ball</b>
<c>Cat</c>
<d>Dog</d>
<e>Elephant</e>
<f>Fox</f>
</AlphReq>
You can use #XmlAnyElement instead.
#XmlAccessorType(XmlAccessType.FIELD)
public class AlphabetReq
{
#XmlAnyElement
private List<Element> allTags = new ArrayList<Element>();
List<Element> getAllTags()
{
return allTags;
}
void setAllTags(List<Element> allTags)
{
this.allTags = allTags;
}
public Map<String, String> getValues()
{
final Map<String, String> retVal = new HashMap<String, String>();
for (Element el : allTags)
{
retVal.put(el.getNodeName(), el.getTextContent());
}
return retVal;
}
}
method GetValues() returns value as expected:
{f=Fox, d=Dog, e=Elephant, b=Ball, c=Cat, a=Apple}
example:
AlphabetReq obj = JAXB.unmarshal(new java.io.File("D:/test.xml"), AlphabetReq.class);
System.out.println(obj.getValues());
JAXB.marshal(obj, System.out);

Categories