I'm using Jackson v2 in a JAX-RS app, and I'm trying to figure out if it is possible
to configure "ObjectMapper" to drop fields with transient modifier, but only during serialisation.
Here's a DTO to illustrate my use case (getters & setters omitted)
public class User {
private String email;
private transient String password;
}
With the above DTO in mind, I would like to have an object mapper that drops
the password field when serialising, and includes it during deserialisation.
The only thing I could find regarding transient is:
MapperFeature.PROPAGATE_TRANSIENT_MARKER
But that config isn't relevant to my requirements.
P.S - No annotation are to be used, as the DTO's are not to be coupled to any library, plus
I don't necessarily have control over them.
Don't know, looks like transient attribute modifier plus PROPAGATE_TRANSIENT_MARKER just does it. Deserialization is straight forward. There's some fuss with the transient marker during serialization, though. You need to provide getters for the fields, otherwise you'll be stuck with an exception "Unrecognized field ... not marked as ignorable".
Reacting to additional requirements I added a version using jackson mixins. Note that the mixin version produces json with an empty password field, while the PROPAGATE_TRANSIENT_MARKER version produces no field at all.
PROPAGATE_TRANSIENT_MARKER version
public class SerializeDeserializeAttributes {
private final ObjectMapper mapper = new ObjectMapper();
public <T> T fromJson(String json, Class<T> c) throws IOException {
synchronized (mapper) {
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false);
return mapper.readValue(json, c);
}
}
public String toJson(Object o) throws JsonProcessingException {
synchronized (mapper) {
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
return mapper.writeValueAsString(o);
}
}
private static final String jsonFull = "{\"name\":\"A\",\"email\":\"a#a\",\"password\":\"a\",\"width\":1,\"height\":1}";
private static final String jsonPartial = "{\"name\":\"A\",\"email\":\"a#a\",\"width\":1,\"height\":1}";
private static final User user = new User("A", "a#a", "a", 1, 1);
#Test
public void serializeDeserialize() throws IOException {
assertEquals(user, fromJson(jsonFull, User.class));
assertEquals(jsonPartial, toJson(user));
assertEquals(user, fromJson(jsonFull, User.class));
assertEquals(jsonPartial, toJson(user));
}
}
Mixin version
public class SerializeDeserializeAttributesMixin {
public abstract class UserMixin {
#JsonSerialize(using = PwdSerializer.class)
transient String password;
}
static class PwdSerializer extends StdSerializer<String> {
public PwdSerializer() {
this(String.class);
}
private PwdSerializer(Class<String> t) {
super(t);
}
#Override
public void serialize(String s, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeString("");
}
}
private static final String jsonFull = "{\"name\":\"A\",\"email\":\"a#a\",\"password\":\"a\",\"width\":1,\"height\":1}";
private static final String jsonPartialMixin = "{\"name\":\"A\",\"email\":\"a#a\",\"password\":\"\",\"width\":1,\"height\":1}";
private static final User user = new User("A", "a#a", "a", 1, 1);
private static final ObjectMapper mapperMixin = new ObjectMapper();
static {
mapperMixin.addMixIn(User.class, UserMixin.class);
}
#Test
public void serializeDeserializeUsingMixin() throws IOException {
assertEquals(user, mapperMixin.readValue(jsonFull, User.class));
assertEquals(jsonPartialMixin, mapperMixin.writeValueAsString(user));
}
}
That's the User class.
class User {
private String name;
private String email;
private transient String password;
private int width;
private int height;
public User() {
}
User(String name, String email, String password, int width, int height) {
this.name = name;
this.email = email;
this.password = password;
this.width = width;
this.height = height;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Float.compare(user.width, width) == 0 &&
Float.compare(user.height, height) == 0 &&
Objects.equals(name, user.name) &&
Objects.equals(email, user.email) &&
Objects.equals(password, user.password);
}
#Override
public int hashCode() {
return Objects.hash(name, email, password, width, height);
}
#Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
", width=" + width +
", height=" + height +
'}';
}
}
Related
I have two POJOs (Person.java and User.java) that contain similar information. See below:
public class Person {
private String first_name;
private String last_name;
private Integer age;
private Integer weight;
private Integer height;
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
}
public class User {
private String name_first;
private String name_last;
private Integer my_age;
private Integer my_weight;
private String social_security;
public String getName_first() {
return name_first;
}
public void setName_first(String name_first) {
this.name_first = name_first;
}
public String getName_last() {
return name_last;
}
public void setName_last(String name_last) {
this.name_last = name_last;
}
public Integer getMy_age() {
return my_age;
}
public void setMy_age(Integer my_age) {
this.my_age = my_age;
}
public Integer getMy_weight() {
return my_weight;
}
public void setMy_weight(Integer my_weight) {
this.my_weight = my_weight;
}
public String getSocial_security() {
return social_security;
}
public void setSocial_security(String social_security) {
this.social_security = social_security;
}
}
I have defined a mapping.json file as shown below using GSON.
{
"columnMap": [
{
"userColumn": "name_first",
"personColumn": "first_name"
},
{
"userColumn": "last_first",
"personColumn": "first_last"
},
{
"userColumn": "my_age",
"personColumn": "age"
},
{
"userColumn": "my_weight",
"personColumn": "weight"
}
]
}
public class Mapping {
private ArrayList<Pair> columnMap;
public Mapping(){
columnMap = new ArrayList<>();
}
public ArrayList<Pair> getColumnMap() {
return columnMap;
}
public void setColumnMap(ArrayList<Pair> columnMap) {
this.columnMap = columnMap;
}
}
I am writing a utility class helper function that converts between a Person and User object the mapped pairs.
public class Pair {
private String userColumn;
private String personColumn;
public String getUserColumn() {
return userColumn;
}
public void setUserColumn(String userColumn) {
this.userColumn = userColumn;
}
public String getPersonColumn() {
return personColumn;
}
public void setPersonColumn(String personColumn) {
this.personColumn = personColumn;
}
public static void main(String args[]){
}
}
My question is below:
As you can see the returnVal object is being set by me (the programmer) to convert from a User POJO to a Person POJO. How do I leverage the pre-defined mapping.json to do this? The reason I am asking is in the future, the mapping.json file may change (maybe the weight mapping no longer exists). So I am trying to avoid re-programming this Utility.userToPerson() function. How can I achieve this? I am thinking Java reflection is the way to go, but I would like to hear back from the Java community.
public class Utility {
public static Person userToPerson(User u){
Person returnVal = new Person();
returnVal.setAge(u.getMy_age()); // <-- Question How do I leverage mapping.json here?
returnVal.setFirst_name(u.getName_first());
returnVal.setLast_name(u.getName_last());
returnVal.setWeight(u.getMy_weight());
return returnVal;
}
}
You can introspect the beans (i.e. User and Person) for the field names and call corresponding getter from User to fetch the value. Later call corresponding setter in Person.
Here I have taken userToPersonFieldsMap for mapping the field, you can load mapping from JSON file and construct the map accordingly.
Important code section is the for loop, where it dynamically calls getter and setter and does the job.
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
public class UserToPersonMapper {
public static void main(String[] args) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
Map<String, String> userToPersonFieldsMap = new HashMap<>();
userToPersonFieldsMap.put("name_first", "first_name");
userToPersonFieldsMap.put("last_first", "first_last");
userToPersonFieldsMap.put("age", "personAge");
//existing user
User user = new User("Tony", "Stark", 20);
//new person - to be initialised with values from user
Person person = new Person();
for (Map.Entry<String, String> entry : userToPersonFieldsMap.entrySet()) {
Object userVal = new PropertyDescriptor(entry.getKey(), User.class).getReadMethod().invoke(user);
new PropertyDescriptor(entry.getValue(), Person.class).getWriteMethod().invoke(person, userVal);
}
System.out.println(user);
System.out.println(person);
}
}
class User {
private String name_first;
private String last_first;
private int age;
public User(String name_first, String last_first, int age) {
this.name_first = name_first;
this.last_first = last_first;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName_first() {
return name_first;
}
public String getLast_first() {
return last_first;
}
public void setName_first(String name_first) {
this.name_first = name_first;
}
public void setLast_first(String last_first) {
this.last_first = last_first;
}
#Override
public String toString() {
return "User{" +
"name_first='" + name_first + '\'' +
", last_first='" + last_first + '\'' +
", age=" + age +
'}';
}
}
class Person {
private String first_name;
private String first_last;
private int personAge;
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public void setFirst_last(String first_last) {
this.first_last = first_last;
}
public String getFirst_name() {
return first_name;
}
public String getFirst_last() {
return first_last;
}
public int getPersonAge() {
return personAge;
}
public void setPersonAge(int personAge) {
this.personAge = personAge;
}
#Override
public String toString() {
return "Person{" +
"first_name='" + first_name + '\'' +
", first_last='" + first_last + '\'' +
", personAge=" + personAge +
'}';
}
}
You can tweak and try it out this example to make it more align with your requirement.
Note:
This solution uses reflection.
lets asume i have a Interface like that:
public interface User extends Element {
String getName();
String getPassword();
}
and a implementing class like that:
public class BaseUser implements User {
#Override
public String getId() {
return id;
}
#Override
public String getName() {
return name;
}
#Override
public String getPassword() {
return password;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
System.out.println("Set name to " + name);
}
public void setPassword(String password) {
this.password = password;
}
private String id;
private String name;
private String password;
}
Now i want to use bytebuddy to create a interceptor/proxy which catches the call onto the setter, store the changed value and call the real method also.
At the end i want to "ask" the interceptor/proxy for the called setter and the changed values.
I tried a lot considering also the tutorials but up to now i found no working solution. Maybe someone could help me pls.
And here is the Interceptor:
public class GenericInterceptor implements InvocationHandler {
#Override
#RuntimeType
public Object invoke(#This Object proxy, #Origin Method method, #AllArguments Object[] args) throws Throwable {
if (isSetter(method, args)) {
intercept(proxy, method, args);
}
return method.invoke(proxy, args);
}
}
Here is my current 'test' code:
public static void main(String[] args) {
final ByteBuddy bb = new ByteBuddy();
final GenericInterceptor interceptor = new GenericInterceptor();
bb.subclass(BaseUser.class)
.method(isDeclaredBy(BaseUser.class).and(isSetter()))
.intercept(MethodDelegation.to(interceptor))
.make()
.load(BaseUser.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);
final BaseUser user = new BaseUser();
user.setName("my name");
}
EDIT:
public interface Element {
String getId();
}
public class GenericInterceptor<T extends Element> {
public GenericInterceptor(Class<T> type) {
this.type = type;
}
public Map<String, Object> getChanges(T obj) {
final String id = obj.getId();
return changes.get(id);
}
#RuntimeType
public void invoke(#This T proxy, #Origin Method method, #AllArguments Object[] args) throws Throwable {
System.out.println("invoke " + method.getName() + " " + Arrays.toString(args));
intercept(proxy, method, args);
}
private Object getCurrentValue(T proxy, final Field field) {
try {
return field.get(proxy);
} catch (IllegalArgumentException | IllegalAccessException e) {
return null;
}
}
private Field getSetterField(Method setter) {
final String setterName = setter.getName();
Field f = assignedFields.get(setterName);
if (f != null) return f;
final String fieldName = Character.toLowerCase(setterName.charAt(3)) + setterName.substring(4);
try {
f = type.getDeclaredField(fieldName);
if (f == null) return null;
f.setAccessible(true);
assignedFields.put(setterName, f);
return f;
} catch (NoSuchFieldException | SecurityException e) {
return null;
}
}
private void intercept(T proxy, Method setter, Object[] args) {
final Field field = getSetterField(setter);
if (field == null)
return;
final Object currentValue = getCurrentValue(proxy, field);
final Object newValue = args[0];
System.out.println("Set from " + currentValue + " to " + newValue);
final String id = proxy.getId();
Map<String, Object> changeMap = changes.get(id);
if (changeMap == null) {
changeMap = new HashMap<>();
}
changeMap.put(field.getName(), currentValue);
changes.put(id, changeMap);
}
private final Map<String, Field> assignedFields = new HashMap<>();
private final Map<String, Map<String, Object>> changes = new LinkedHashMap<>();
private final Class<T> type;
}
You can call orignal method using MethodDelegation.to(...).andThen(SuperMethodCall.INSTANCE).
public class ByteBuddyTest {
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
GenericInterceptor interceptor = new GenericInterceptor ();
Class<?> clazz = new ByteBuddy()
.subclass(BaseUser.class)
.method(ElementMatchers.isDeclaredBy(BaseUser.class).and(ElementMatchers.isSetter()))
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.to(interceptor))))
.make()
.load(ByteBuddyTest.class.getClassLoader())
.getLoaded();
BaseUser user1 = (BaseUser) clazz.getConstructors()[0].newInstance();
BaseUser user2 = (BaseUser) clazz.getConstructors()[0].newInstance();
user1.setName("user1");
user1.setPassword("password1");
user2.setName("user2");
user2.setPassword("password2");
System.out.println(interceptor.getInterceptedValue("user1", "name"));
System.out.println(interceptor.getInterceptedValue("user1", "password"));
System.out.println(interceptor.getInterceptedValue("user2", "name"));
System.out.println(interceptor.getInterceptedValue("user2", "password"));
user1.setPassword("password2");
user1.setPassword("password3");
}
public static class GenericInterceptor {
private Map<String, Object> interceptedValuesMap = new HashMap();
public void set(String obj, #This User user, #Origin Method setter) {
// assume that user name is unique so we can use it as a key in values map.
// or define equals/hashcode in GenericUser object and use it as a key directly
String setterName = setter.getName();
String propertyName = setterName.substring(3, setterName.length()).toLowerCase();
String key = user.getName() + "_" + propertyName;
System.out.println("Setting " + propertyName + " to " + obj);
System.out.println("Previous value " + interceptedValuesMap.get(key));
interceptedValuesMap.put(key, obj);
}
public Object getInterceptedValue(String userName, String fieldName) {
return interceptedValuesMap.get(userName + "_" + fieldName);
}
}
public static interface User {
String getName();
String getPassword();
}
public static class BaseUser implements User {
#Override
public String getName() {
return name;
}
#Override
public String getPassword() {
return password;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
private String name;
private String password;
}
}
I use fasterxml in 2.6.4 and getting the following JSON by an external service on which I have no influence on the given output:
{
"name": "dunnosName",
"widthValue": 46.1,
"heightValue": 56.1,
"depthValue": 66.1,
"unit": "mm"
}
and want to map it to the following POJOs:
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
}
public class ValueWithUnit {
private Float value;
private String unit;
}
My excepted mapping should look something like this:
name -> Dunno.name
widthValue -> Dunno.width.value
heightValue -> Dunno.height.value
depthValue -> Dunno.depth.value
unit -> Dunno.width.unit
unit -> Dunno.height.unit
unit -> Dunno.depth.unit
Is it possible to realize the expected mapping using fasterxml? And if so which fasterxml annotations or classes do I have to implement to realize this mapping?
You don't need a transitional TempDunno. You need a Custom Deserializer. This is a textbook example where you would use one. Add the following annotation to Dunno class:
#JsonDeserialize(using = DunnoDeserializer.class)
and here it is, and with input validation as well:
#SuppressWarnings("serial")
public class DunnoDeserializer extends StdDeserializer<Dunno>
{
public DunnoDeserializer()
{
this(null);
}
public DunnoDeserializer(Class<?> vc)
{
super(vc);
}
#Override
public Dunno deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
Dunno dunno = new Dunno();
// first parse the input into a map, which is more convenient to work with
#SuppressWarnings("unchecked")
Map<String, Object> values = jp.getCodec().readValue(jp, Map.class);
dunno.name = values.containsKey("name") ? values.get("name").toString() : "empty";
String unit = values.containsKey("unit") ? values.get("unit").toString() : "default-units";
if (values.containsKey("widthValue")) {
dunno.width = new ValueWithUnit();
dunno.width.value = ((Number)values.get("widthValue")).floatValue();
dunno.width.unit = unit;
}
if (values.containsKey("heightValue")) {
dunno.height = new ValueWithUnit();
dunno.height.value = ((Number)values.get("heightValue")).floatValue();
dunno.height.unit = unit;
}
if (values.containsKey("depthValue")) {
dunno.depth = new ValueWithUnit();
dunno.depth.value = ((Number)values.get("depthValue")).floatValue();
dunno.depth.unit = unit;
}
System.out.println(values);
values.values().forEach(v -> System.out.println(v.getClass()));
return dunno;
}
}
test method:
public static void main(String[] args)
{
String jsonString = "{ \"name\": \"dunnosName\"," + "\"widthValue\": 46.1," + "\"heightValue\": 56.1,"
+ "\"depthValue\": 66.1," + "\"unit\": \"mm\"}";
ObjectMapper mapper = new ObjectMapper();
try {
Dunno d = (Dunno)mapper.readValue(jsonString, Dunno.class);
System.out.format("%s: %.2f(%s) %.2f(%s) %.2f(%s)",
d.name, d.width.value, d.width.unit, d.height.value, d.height.unit, d.depth.value, d.depth.unit);
} catch (IOException e) {
e.printStackTrace();
}
}
which gives expected output:
dunnosName: 46.10(mm) 56.10(mm) 66.10(mm)
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ValueWithUnit getWidth() {
return width;
}
public void setWidth(ValueWithUnit width) {
this.width = width;
}
public ValueWithUnit getHeight() {
return height;
}
public void setHeight(ValueWithUnit height) {
this.height = height;
}
public ValueWithUnit getDepth() {
return depth;
}
public void setDepth(ValueWithUnit depth) {
this.depth = depth;
}
#Override
public String toString() {
return "Dunno{" +
"name='" + name + '\'' +
", width=" + width +
", height=" + height +
", depth=" + depth +
'}';
}
}
public class ValueWithUnit {
private Float value;
private String unit;
public ValueWithUnit(Float value, String unit) {
this.value = value;
this.unit = unit;
}
public Float getValue() {
return value;
}
public void setValue(Float value) {
this.value = value;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
#Override
public String toString() {
return "ValueWithUnit{" +
"value=" + value +
", unit='" + unit + '\'' +
'}';
}
}
public class TempDunno {
private String name;
private Float widthValue;
private Float heightValue;
private Float depthValue;
private String unit;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getWidthValue() {
return widthValue;
}
public void setWidthValue(Float widthValue) {
this.widthValue = widthValue;
}
public Float getHeightValue() {
return heightValue;
}
public void setHeightValue(Float heightValue) {
this.heightValue = heightValue;
}
public Float getDepthValue() {
return depthValue;
}
public void setDepthValue(Float depthValue) {
this.depthValue = depthValue;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
#Override
public String toString() {
return "TempDunno{" +
"name='" + name + '\'' +
", widthValue=" + widthValue +
", heightValue=" + heightValue +
", depthValue=" + depthValue +
", unit='" + unit + '\'' +
'}';
}
}
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\n" +
" \"name\": \"dunnosName\",\n" +
" \"widthValue\": 46.1,\n" +
" \"heightValue\": 56.1,\n" +
" \"depthValue\": 66.1,\n" +
" \"unit\": \"mm\"\n" +
"}";
System.out.println(getDunno(json));
}
private static Dunno getDunno(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
TempDunno tmp = mapper.readValue(json, TempDunno.class);
Dunno dunno = new Dunno();
dunno.setName(tmp.getName());
dunno.setHeight(new ValueWithUnit(tmp.getHeightValue(), tmp.getUnit()));
dunno.setWidth(new ValueWithUnit(tmp.getWidthValue(), tmp.getUnit()));
dunno.setDepth(new ValueWithUnit(tmp.getDepthValue(), tmp.getUnit()));
return dunno;
}
}
I am using jackson 2.2 annotation #JsonProperty with required set to true. While deserializing json file which doesn't contain that property via ObjectMapper readValue() method no exception is being thrown.
Is it supposed to work in a different way or did I missed something?
My dto class:
public class User {
public enum Gender {MALE, FEMALE}
;
public static class Name {
private String _first, _last;
public String getFirst() {
return _first;
}
public String getLast() {
return _last;
}
public void setFirst(String s) {
_first = s;
}
public void setLast(String s) {
_last = s;
}
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
#JsonProperty(value ="NAAME",required = true)
public Name getName() {
return _name;
}
#JsonProperty("VERIFIED")
public boolean isVerified() {
return _isVerified;
}
#JsonProperty("GENDER")
public Gender getGender() {
return _gender;
}
#JsonProperty("IMG")
public byte[] getUserImage() {
return _userImage;
}
#JsonProperty(value ="NAAME",required = true)
public void setName(Name n) {
_name = n;
}
#JsonProperty("VERIFIED")
public void setVerified(boolean b) {
_isVerified = b;
}
#JsonProperty("GENDER")
public void setGender(Gender g) {
_gender = g;
}
#JsonProperty("IMG")
public void setUserImage(byte[] b) {
_userImage = b;
}
}
This is how do I deserialize the class:
public class Serializer {
private ObjectMapper mapper;
public Serializer() {
mapper = new ObjectMapper();
SimpleModule sm = new SimpleModule("PIF deserialization");
mapper.registerModule(sm);
}
public void writeUser(File filename, User user) throws IOException {
mapper.writeValue(filename, user);
}
public User readUser(File filename) throws IOException {
return mapper.readValue(filename, User.class);
}
}
This is how it is actually called:
Serializer serializer = new Serializer();
User result = serializer.readUser(new File("user.json"));
Actuall json looks like:
{"GENDER":"FEMALE","VERIFIED":true,"IMG":"AQ8="}
I would expect that since _name is not specified in json file and is required that the exception will be thrown.
With Jackson 2.6 you can use required, however you have to do it using JsonCreator
For example:
public class MyClass {
#JsonCreator
public MyClass(#JsonProperty(value = "x", required = true) Integer x, #JsonProperty(value = "value_y", required = true) Integer y) {
this.x = x;
this.y = y;
}
private Integer x;
private Integer y;
}
If x or y are not present an exception will be thrown when trying to deserialize it.
As per Jackson annotations javadocs: "Note that as of 2.0, this property is NOT used by BeanDeserializer: support is expected to be added for a later minor version."
That is: no validation is performed using this settings. It is only (currently) used for generating JSON Schema, or by custom code.
I can get my data, because i get an error on line 66 which is. but error saying that I get a null value. although I've looked through the code, I think even that, it gets the right value in. I tried using a method that I made just for it. but after that it did not work, I used a method that works, which I use to log in with.
label_KontoId.setText(myPrivate.getAccountName());
My class's looks like this: In my main i got this code
public void SetId(String AccountId, String kode) {
AccountName = AccountId;
Password = kode;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PrivatekunderGUI frame = new PrivatekunderGUI();
frame.setVisible(true);
myPrivate = PR.LogindCheck(AccountName, Password);
} catch (Exception e) {
e.printStackTrace();
}
}
});
label_KontoId.setText(myPrivate.getAccountName());
}
This is not all the code, just what's necessary. The other code is generated for the GUI:
public class Private extends Customers {
private String AccountName;
private String Password;
private int Balance;
private int AccountId;
public Private(String Name, int Number, int Zip, String Address, int Phone,
int Balance, int AccountId, String AccountName, String Password) {
super(Name, Number, Zip, Address, Phone);
this.AccountId = AccountId;
this.Balance = Balance;
this.AccountName = AccountName;
this.Password = Password;
}
public String getAccountName() {
return AccountName;
}
public String getPassword() {
return Password;
}
public int getBalance() {
return Balance;
}
public int getAccountId() {
return AccountId;
}
public void setAccountName(String accountName) {
AccountName = accountName;
}
public void setPassword(String password) {
Password = password;
}
public void setBalance(int balance) {
Balance = balance;
}
public void setAccountId(int accountId) {
AccountId = accountId;
}
void account() {
}
#Override
public String toString() {
return "Private [AccountName=" + AccountName + ", Password=" + Password
+ ", Balance=" + Balance + ", AccountId=" + AccountId
+ ", getName()=" + getName() + ", getNumber()=" + getNumber()
+ ", getZip()=" + getZip() + ", getAddress()=" + getAddress()
+ ", getPhone()=" + getPhone() + "]";
}
}
and my PrivateRegistre looks like this:
public class PrivateRegistre {
private ArrayList<Private> privater = new ArrayList<>();
public PrivateRegistre() {
gem("Driton", 32233223, 2400, "Hallovej 54", 32233223, 543442, 1,
"Driton", "1234");
}
public void gem(String Name, int Number, int Zip, String Address,
int Phone, int Balance, int AccountId, String AccountName,
String Password) {
privater.add(new Private(Name, Number, Zip, Address, Phone, Balance,
AccountId, AccountName, Password));
}
public ArrayList<Private> hentalleprivatekunder() {
return privater;
}
public Private findkunde(int AccountId) {
for (Private privat : privater) {
if (privat.getAccountId() == AccountId) {
return privat;
}
}
return null;
}
public Private LogindCheck(String AccountName, String Password) {
for (Private privat : privater) {
if (privat.getAccountName().equals(AccountName)
&& privat.getPassword().equals(Password)) {
return privat;
}
}
return null;
}
public boolean sletprivatekunde(int AccountId) {
Private privat = findkunde(AccountId);
if (privat == null)
return false;
privater.remove(privat);
return true;
}
#Override
public String toString() {
return "PrivateRegistre [Private Kunder=" + privater + "]";
}
public Private HentLogindOplysninger(String AccountName) {
for (Private privat : privater) {
if (privat.getAccountName().equals(AccountName)) {
return privat;
}
}
return null;
}
}
Because you are returning null in your methods
findkunde(...)
HentLogindOplysninger(...)
LogindCheck(...)
You shouldn't be returning null - return something useful and if you have nothing to return better use void in method return type
myPrivate = PR.LogindCheck(AccountName, Password); here you are getting null beacuse you are returning null in method
public Private LogindCheck(String AccountName, String Password)
& also in
public Private findkunde(int AccountId)
just replacereturn null statement with something that would make sense and can be assigned and then used without resulting into NullPointerException;