I have a task where object properties need to be populated from data received via JSON web service. The property names are mapped to the JSON keys. I am using the following code in an attempt to populate the object but the app crashes when it hits this line:
while(looper.hasNext()){
String key = looper.next();
String val = json.get(key).toString();
user.getClass().getDeclaredField(key).set(user, val); // crash
}
The object is called user. I have verified that the key variable does match a property in the user object. Any ideas on how to fix this? THanks!
you should set your field accessible
Field field = user.getClass().getDeclaredField(key);
if (field != null) {
field.setAccessible(true);
field.set(user, val);
}
Related
I have an object with some fields and they have setters. I want to iterate through a map from a request and based on the key name with value null - unset the field by doing something like
field1.set[key](null)
instead of having the request be a list and doing
list.forEach() {
if (list.contains(key)) {
object.setKeyName(null);
}
}
Is this possible? It would be more dynamic vs having to add a new if statement each time a new field is added to the model. Disregard sanitization of the input.
You can do that using Reflection.
for (String fieldName : list) {
Class parameterType; //get the type
object.getClass().getDeclaredMethod("set" + fieldName, parameterType).invoke(object, null);
}
I'm trying to pass a payload to a validate(ValidationPayload) in the Play Framework using Java. I can not access the values stored in payload.getAttrs() which returns a TypedMap.
I tried to access the Cookies by calling in the validate method payload.getAttrs().getOptional(TypedKey.create("Cookies")) but I always get a null back.
When I evaluate expression using IntelliJ I see the attrs contain Cookies, Flash and more. But I can not access theses values. I can see the values in the Expression Evaluator screenshot
public String validate(Constraints.ValidationPayload payload) {
TypedMap attrs = payload.getAttrs();
Optional<Object> baseDomain = payload.getAttrs().getOptional(TypedKey.create("baseDomain"));
Locale value = payload.getAttrs().get(TypedKey.create("selectedLang"));
return "String";
}
How can I access these objects stored in a TypedMap?
I figured this out a TypedMap map uses TypedKeys. A typed key is unique to each INSTANCE of the key.
That means you need to fetch from the typedMap with the same instance of the key that was used to put in the map. Creating a new key will cause an empty or null response.
This should work:
TypedKey<String> baseDomainKey = TypedKey.create("baseDomain")
payload.getAttrs().addAttrs(baseDomainKey, "domain")
String domain = payload.getAttrs().get(baseDomainKey)
This will not work however:
TypedKey<String> baseDomainKey = TypedKey.create("baseDomain")
payload.getAttrs().addAttrs(baseDomainKey, "domain")
String domain = payload.getAttrs().get(TypedKey.create("baseDomain"))
I am iterating over the fields of GPB message and have to find out the list of fields which have been set in the message
public void printFields(Person person){
Builder builder = person.toBuilder();
Descriptor descriptor = Person.getDescriptor();
List<FieldDescriptor> fields = descriptor.getFields();
for(FieldDescriptor fd : fields){
Object value = builder.get(fd); //this gives the value
// how to check if this field is set or not
}
}
Checking value for null doesnot help as there can be primitive types in the message as well.
I have read about hasXXX() methods on the message class which tells whether XXX has default value or explicit value, but how to invoke these using builder/descriptor/fieldDescriptor.
If you are using Java 8, you can find the defined fields using the streaming api:
List<Descriptors.FieldDescriptor> definedPersonFields = Person.getDescriptor()
.getFields()
.stream()
.filter(Person::hasField)
.collect(Collectors.toList())
It is late, but may be useful for other people..
The below code will print modified attribute name and its value. you can change it identify populated attributes in proto
Map<Descriptors.FieldDescriptor, Object> modifiedFields = proto.getAllFields();
for(Descriptors.FieldDescriptor fieldDescriptor : modifiedFields.keySet())
{
int protNum = fieldDescriptor.toProto().getNumber();
Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
Object value = modifiedFields.get(fieldDescriptor);
System.out.println(fieldDescriptor.getFullName());
System.out.println(value);
}
Why do you need to use descriptor/fieldDescriptor? They are even not available if you define "option optimize_for = LITE_RUNTIME".
Anyway, you can do it already on a Person.Builder or just Person, e.g.:
Builder builder = person.toBuilder();
if (builder.hasXXX()){
XXX xxx = builder.getXXX();
}
I am serializing a POJO using jackosn, and I want that all the values for which the user sets some value irrespective whether it's null or not must be included in the serialization.
So currently:
POJO:
public class YourItem {
public String key;
public String item;
}
Currently when user does:
YourItem item = new YourItem();
item.setKey("abc");
The serialization gives:
{
"key" : "abc"
}
as I configured ObjectMapper as objectMapper.setInclude(Include.NON_NULL)
However now if the user specifically calls the setter and sets the value as null, then I want that item in my serialized string.
So if user does
YourItem item = new YourItem();
item.setKey("abc");
item.setItem(null);
I want in serialzation both key and item values are present like:
{
"key" : "abc",
"item" : null
}
How do I differentiate between the user set null and the default null.
Is there a configuration in ObjectMapper ??
Some people consider using null to be bad practice (The book Clean Code, for instance)
Disregarding that, you cannot differentiate between the default initialization null and a user-set null by language-design
You need some sort of state that tracks if a field has been accessed by a setter. If it hasn't been accessed by a setter and is null, ignore it.
One way to do this is Jackson Filters, which allows you to define various conditions for serializing a field during runtime (your condition being that your setter-access-state indicates that the field was set by a user)
http://www.baeldung.com/jackson-serialize-field-custom-criteria
i am very new to JAVA 8 and SPRING MVC . I have a java bean which is a POJO with setter and getter. My Spring web service using reflection maps the request parameters to the POJO.
I want to do input validation using annotation. I have a requirement were i need to read all the values of the annotated field and check atleast one value is provided. I wrote a sample code.... BUT NOT SURE HOW TO GET THE VALUES THAT ARE ASSIGNED TO A FIELD. Please do share sample code if you have:
public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
boolean canProceed = false;
for(Field field : DocumentSearchRequest_global.class.getDeclaredFields())
{
if (field.isAnnotationPresent(ValidDocumentModifiedDate.class))
{
String name = field.getName();
//IAM ABLE TO GET THE NAME OF THE FIELD
System.out.println("1.name : "+ name);
System.out.println("2. "+field.getType().getName());
}
}
// Method[] method = DocumentSearchRequest_global.class.getDeclaredMethods();
for (Method method :DocumentSearchRequest_global.class.getDeclaredMethods() )
{
System.out.println(method.getName() );
//ABLE TO GET NAME OF THE GETTER AND SETTER METHODS IN THE POJO
//CAN U SUGGEST HOW TO READ THE VALUE OF A PARTICULAR FIELD.. EITHER BY //GETTING THE VALUE FROM THE GET METHOD??? ...
}
You can get the values by calling method.invoke(Object, Object...) where first parameter is your class instance on which method is to be executed and second variable arguments are arguments of the method. In your case it'll be null or empty. Here is simple code snippet Object value = method.invoke(DocumentSearchRequest_global_instance);