Skip marshalling with #XStreamConverter ToAttributedValueConverter when value is null - java

I have the following POJO which I would like to marshal using the #XStreamConverter ToAttributedValueConverter:
#XStreamAlias("MyPojo")
#XStreamConverter(value = ToAttributedValueConverter.class, strings = {"content"})
public class MyPojo{
private final String content;
private final String attribute1;
private final String attribute2;
public UniqueReportIDIss(String content, String attribute1, String attribute2) {
this.content = content;
this.attribute1 = attribute1;
this.attribute2 = attribute2;
}
}
The ToAttributedValueConverter marshals this nicely to:
<MyPojo attribute1="foo" attribute2="bar">content</MyPojo>
This is just what I need in 99% of all use cases. However, in one particular use case, if the content is null, the marshaling must be skipped.
Currently, if the value is null, it results in:
<MyPojo attribute1="foo" attribute2="bar"></MyPojo>
The Javadocs of ToAttributedValueConverter explicitly state that null values are permitted, thus the question: How can I extend ToAttributedValueConverter so that it skips marshaling when the value is null.
Thanks
Walter

Related

Why is gson changing my Base64 encodeing and how to prevent it

I have the following data
String text = "ZG9udCB0b3VjaCBtZQ==";
MqttMessageDTO data = new MqttMessageDTO("topic", text, "id", 1L);
String a = gson.toJson(data);
Where MqttMessageDTO looks like
public class MqttMessageDTO {
private String topic;
private String base64EncodedMessage;
private String externalVehicleIdentifier;
private Long timestamp;
}
(excluding getters and constructor)
This generates the following output:
{"topic":"topic","base64EncodedMessage":"ZG9udCB0b3VjaCBtZQ\u003d\u003d","externalVehicleIdentifier":"id","timestamp":1}
Where the base64EncodedMessage field has been changed and == has been replaced with \u003d\u003d.
Why is this happening and how can I prevent this from happening. I dont want gson to make any changes while serializing and deserializing the base64EncodedMessage field.
Gson version:
2.8.5

reading the value of an array of json and putting it into set through java

I am using Jackson library with java 11 so basically I am able to read the below JSON into a string format
{
"schemas":[
"urn:params:core:2.0:User",
"urn:params:core:3.0:User"
],
},
}
here below is the set in which I have to fill the values of schemas from above json
private Set<String> setschemas = null;
right now I am able to read the above json into a string named finaljson , now please advise how can I read the differnt value of schemas from above json string named finaljson and set it to set named setschemas
if (node.has("schemas")) {
// *** here I want to read the differernt value of schemas and set it to a set
// named setschemas
// *****
}
you can create the following classes that represent the json structure
class MyJsonObject {
private AppIdentity appIdentity;
private Set<String> schemas;
private String userName;
}
class AppIdentity {
private String clientId;
private String username;
}
than you can use
final MyJsonObject myJsonObject = new ObjectMapper().readValue(finaljson, MyJsonObject.class); to read the json to JAVA object
so it can manipulated like myJsonObject.schemas.size() > 0 and such...
there are a lot of examples in the internet
*keep in mind, this solution only works when the json structure and fields name are known in advanced
With your approach, this would be simplest one:
if(node.has("schemas")) {
JsonNode schemaNode = node.get("schemas");
Set<String> schemaSet = objectMapper.convertValue(schemaNode, Set.class);
System.out.println("schemaSet" + schemaSet);
}
There are various ways to deal with JSON one is described here
1) You can create a class of JSON structure as follows with help online JSON to POJO convertor (Note:: Add Setters and Getters with help of IDE)
class AppJson {
private Set<AppIdentity> appIdentity;
private Set<String> schemas;
private String userName;
private Manager ManagerObject;
private String division;
private String organization;
private String costCenter;
private String employeeNumber;
}
class AppIdentity {
private String clientId;
private String username;
}
class Manager {
private String value;
private String $ref;
private String displayName;
private String $Ref;
}
2) Use above for object conversion.
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{\"appIdentity\":[{\"clientId\":\"9a41763c642\",\"username\":\"XXX\"}],\"schemas\":[\"urn:params:core:2.0:User\",\"urn:params:core:3.0:User\"],\"userName\":\"ajklmnop_699100\",\"manager\":{\"value\":\"string\",\"$ref\":\"sdkoirk\",\"displayName\":\"string\",\"$Ref\":\"sdkweoirk\"},\"division\":\"string\",\"organization\":\"string\",\"costCenter\":\"string\",\"employeeNumber\":\"string\"}\n"
+ "";
AppJson appJson = objectMapper.readValue(jsonString, AppJson.class);
System.out.println("json " + appJson.getSchemas());
Here you will get the schemas.

Object mapping fields

I have an objects class A:
public class A {
private Long id;
private String name;
private String mail;
private String moreData;
// ...
}
class B:
public class B {
private Long id;
private String name;
private String crc;
// ...
}
Can I use jackson to provide field mapping from object A to B copying correspond fields into target object.
I need from object
A {
Long id = 23L;
String name = "name";
String mail = "mail";
String moreData = "moreData";
// ...
}
get as target object
B {
Long id = 23L;
String name = "name";
String crc = mull;
// ...
}
after object mapping processing...
Is it possible implement solution using com.fasterxml.jackson in simple way?
Sure you can. Not withstanding a full understanding of why you want to do this, or that I think there might be more efficient ways than converting to JSON then back, but if you would like to use Jackson, here is what I would do:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
B b = objectMapper.readValue(objectMapper.writeValueAsString(a), B.class);
Hope this helps. should do the job. The key will be to tell Jackson to not fail on unknown properties so it drops those you are not sure of.

Serializing to XML using XStream but not getting all fields

I have a class called Lookup that has two properties:
public class Lookup {
private String surveyName;
private String GUID;
public Lookup(String name, String guid){
this.surveyName = name;
this.GUID = guid;
}
}
In another class, I have a list of Lookup that I am trying to serialize and save to file. This is how I'm doing it:
List<Lookup> lookup = new ArrayList<Lookup>();
lookup.add(new Lookup("foo","bar"));
XStream serializer = new XStream();
serializer.alias("Lookups",List.class);
String xml = serializer.toXML(lookup);
The XML I end up with is:
<Lookups>
<Lookup>
<GUID>bar</GUID>
</Lookup>
</Lookups>
As you can see, it only serialized the field GUID but not the field surveyName. Why is it ignoring that field?
Are you sure that you don't modify Lookup variable somewhere else. This code runs fine
public class Test {
public static void main(String[] args) {
List<Lookup> lookup = new ArrayList<Lookup>();
lookup.add(new Lookup("foo","bar"));
XStream serializer = new XStream();
serializer.alias("Lookups",List.class);
String xml = serializer.toXML(lookup);
System.out.println(xml);
}
}
class Lookup {
private String surveyName;
private String GUID;
public Lookup(String name, String guid){
this.surveyName = name;
this.GUID = guid;
}
}
Output:
<Lookups>
<Lookup>
<surveyName>foo</surveyName>
<GUID>bar</GUID>
</Lookup>
</Lookups>
Silly me, the mistake was completely on my end. The field name was receiving an empty string, and thus XStream must have been ignoring it.

Byte array is not working in JAXB classes

I am trying to use byte array like this (JAXB class). However, I am getting all 0s in the msg field even though I pass valid characters. The "id" and "myid" fields are parsed successfully and it is failing for the byte array field.
#XmlRootElement(name = "testMessage")
#XmlAccessorType(XmlAccessType.FIELD)
public class TestMessage
{
#XmlAttribute
private Integer id;
#XmlElement(name = "myid")
private Long myid;
#XmlElement(name = "msg")
private byte[] msg;
}
Using JAXB of Java 1.6.0_23 i get the following xml file for a TestMessage instance:
TestMessage testMessage = new TestMessage();
testMessage.id = 1;
testMessage.myid = 2l;
testMessage.msg = "Test12345678".getBytes();
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testMessage id="1">
<myid>2</myid>
<msg>VGVzdDEyMzQ1Njc4</msg>
</testMessage>
If you unmarshall this xml content you should get back the TestMessage instance including the msg byte array (which is base64 encoded in the xml file).
You can use xml adapters for your byte array xml element. As you now, every element get marshalling/unmarshalling and adapters are use for situations such as converting date time with specified format, type convertions etc. while marshalling/unmarshalling.
HexBinaryAdapter class is one of those adapters belongs to javax.xml.bind.annotation.adapters so you can use it.
public class TestMessage {
#XmlAttribute
private Integer id;
#XmlElement(name = "myid")
private Long myid;
#XmlJavaTypeAdapter(HexBinaryAdapter.class)
#XmlElement(name = "msg")
private byte[] msg;
}
Yet, if you prefer a custom convertion, you can create your own adapter for converting bytes for a specified format such as base64 etc.
To do that you must write your own unmarshalling/marshalling methods,
public final class MyAdapter extends XmlAdapter<String, byte[]> {
public byte[] unmarshal(String s) {
if (s == null)
return null;
return decode()); // your way to decode.
}
public String marshal(byte[] bytes) {
if (bytes == null)
return null;
return encode(); //your way to encode
}
}
then you give your marshaller/unmarshaller in #XmlJavaTypeAdapter anotation ;
public class TestMessage {
#XmlAttribute
private Integer id;
#XmlElement(name = "myid")
private Long myid;
#XmlJavaTypeAdapter(MyAdapter.class)
#XmlElement(name = "msg")
private byte[] msg;
}

Categories