GSON - JSON to Java object - java

I have been applying my expert level googling skills to no avail, so Stackoverflow I need your assistance.
I want to convert my json object to a java object in java.
JSON object appears as...
- {"password":"b","userName":"a"}
and the print statements once i 'attempt' to convert it are...
username = b
password = null
my question is why is this happening and how can i solve the issue? (Code follows)
Gson gson = new Gson();
JSONObject jObj = new JSONObject(request.getParameter("input"));
User user = gson.fromJson(jObj.toString(), User.class);
System.out.println(user.getPassword());
System.out.println(user.getUsername());
and the 'model' class....
public class User {
private String username;
private String password;
public User(String uName, String pWord){
this.username = uName;
this.password = pWord;
}
public void setUsername(String uName){
username = uName;
}
public String getUsername(){
return username;
}
public void setPassword(String pWord){
password = pWord;
}
public String getPassword(){
return password;
}
}

The solution in this case was was related to the mapping in the JSON as 'userName' when it should have been 'username'
refer to the comments for additional information.
hopefully other users find this a useful resource.

Related

"Bad return type in lambda expression: String cannot be converted to void" in .forEach method

I have a class Users with, among others, a List of user objects, the following method, which is supposed to
build a list of String
check if an incoming String is contained in that list.
public class Users {
List<User> users;
public Users(List<User> users) {
this.users = new ArrayList<>();
}
#...
public boolean checkUserExists(String targetUserID) {
List<String> userIDS = users.forEach(user -> user.userID);
return userIDS.contains(targetUserID);
}
}
But, under the lambda expression, SonarLint shows the "Bad return type in lambda expression: String cannot be converted to void" error.
This is how the class User is implemented:
package menus.DataStructures;
public class User {
String userType;
String userID;
String userName;
int userAge;
protected User(String userType, String userID, String userName, int userAGe) {
this.userType = userType;
this.userID = userID;
this.userName = userName;
this.userAge = userAGe;
}
}
In my mind, there shouldn't be a problem, but I'm almost new to Java and I come from JS and Python. I have read answers addressing the same error message but due to my Java ignorance I haven't been able to understand anything.
What causes this error?
It looks like what you're looking for is map and not forEach:
public boolean checkUserExists(String targetUserID) {
List<String> userIDS = users.stream().map((user) -> user.userID).collect(Collectors.toList())
// if you're using java 16+ you can replace .collect(...) with .toList();
return userIDS.contains(targetUserID);
}

How can I handle the response from the retrofit (Here my response not showing the data, it only shows the code and status of the call)

I am using retrofit to do the api call from my android app. But the response shows the status code 200 with ok message.
But the data for the call is return by httpClient.
So how can I handle the response data of my call.
Here the response will be
request payload
/okhttp.OkHttpClient: {"data":{"email":"foobar#gmail.com","password":"PASSWoRD121"}}
response:
okhttp.OkHttpClient: {"data":"my tokken"}
Here is my printed response will not give the above data. How can I set the token to my next calls?
response ==== Response{protocol=http/1.1, code=200, message=OK, url="http://tyhgfhfty/hfhgfh/"}
ApiService.java
#POST(ApiConstant.Login)
Call<User> LoginRequest(#Body JsonObject user);
LoginActivity:
ApiService userLoginService = retrofit.create(ApiService.class);
final JsonObject jo = new JsonObject();
jo.addProperty(ApiParameter.EMAIL, email);
jo.addProperty(ApiParameter.PASSWORD, password);
final JsonObject jobj = new JsonObject();
jobj.add(ApiParameter.DATA, jo);
userLoginService.userLogin(jobj).enqueue(new Callback<LoginRequest>(){
#Override
public void onResponse(Call<LoginRequest> call, Response<LoginRequest>response) {
System.out.println(("response ===" + response));
LoginRequest.java
public class LoginRequest {
private String email;
private String password;
public void setEmail(String email) {
this.email = email;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
}
When you have a json response, you can analyze or presume a json is equal a class, because Gson convertion.
In that json is containing a key data and a string my tokken.
In a class retrofit response it is equal variable named data which is from key data with type String, why String? because value my tokken is a string in that json. So you can retrieve that value later from data getter setter. Like getData();
So for {"data":"my tokken"}, your LoginResponse class only contain one field that is data with type String and the setter getter.
When you have response {"data": {"user": "xxxx", "email": "foobar#gmail.com", "lastname": "yyyyy", "gender": 1, "deviceType": 1}"}. You can analyze that key data contain a json object; a json equal a class.
So, you need a class to get accessibility to it value. Let's say it User class.
public class User {
private String user; // because the value of user in json is String
private String email;
private String lastname;
private Int gender; // because the value of gender in json is Int
private Int deviceType;
// the setter getter here
}
Last, your class response that handle the retrofit call. Let say UserResponse should be like this
public class UserResponse {
private User data;
// the variable is named data because it should be the same to the json key and the type of the variable is class `User`. Remember about the bolded text
// (variable named same is not a must, if different, you can use `SerializedName` annotation, you can read about it later)
// the setter getter here
}
I explained in simple way of my thinking, i hope you understand about it.

Java Spring hash AND validate passwords

I'm pulling my hair out over this. I have a simple User entity like this
#Entity
public class User {
private static final PasswordEncoder pwEncoder = new BCryptPasswordEncoder();
#Id
#GeneratedValue
private long id;
#NotNull(message = "FIELD_IS_NULL")
#NotEmpty(message = "FIELD_IS_REQUIRED")
#Length(min = 3, message = "FIELD_MUST_HAVE_AT_LEAST_3_CHARACTERS")
private String username;
#NotNull(message = "FIELD_IS_NULL")
#NotEmpty(message = "FIELD_IS_REQUIRED")
#Length(min = 6, message = "FIELD_MUST_HAVE_AT_LEAST_6_CHARACTERS")
#Pattern(regexp = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,128}$", message="PW_MIN_6_MAX_128_1_UPPER_1_LOWER_1_NUMERIC")
private String password;
public User(String username, String password){
this.username = username;
this.password = pwEncoder.encode(password);
}
/* getters and setters */
}
This works fine except that the password hashing happens before any validation, which means that the hashed password is validated instead of the unhashed.
I'm using a PagingAndSortingRepository for all my repository needs and I'd really like to avoid implementing a controller just for this case.
I'm feeling like I'm missing something really big there...
If you using this constructor
public User(String username, String password){
this.username = username;
this.password = pwEncoder.encode(password);
}
you'll have encoded password instead of original value
you can make #PrePersist method like this:
#PrePersist
public void prePersist(){
password = pwEncoder.encode(password);
}

gson.fromJson return null values

This is My JSON String : "{'userName' : 'Bachooo'}"
Converting JSON String to LoginVO logic is:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
LoginVO loginFrom = gson.fromJson(jsonInString, LoginVO.class);
System.out.println("userName " + loginFrom.getUserName()); // output null
My LoginVO.class is:
public class LoginVO {
private String userName;
private String password;
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
Note I am using jdk 1.8.0_92
Output of loginForm.getUserName() is NULL instead of "Bachooo" any idea about this issue?
Since you are setting excludeFieldsWithoutExposeAnnotation() configuration on the GsonBuilder you must put #Expose annotation on those fields you want to serialize/deserialize.
So in order for excludeFieldsWithoutExposeAnnotation() to serialize/deserialize your fields you must add that annotation:
#Expose
private String userName;
#Expose
private String password;
Or, you could remove excludeFieldsWithoutExposeAnnotation() from the GsonBuilder.
Adding what resolved this for me.
So in my API following gson implementation was getting used:
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
I had to use the same implementation in my test, before which gson was failing to parse attributes.
So in essence check how your gson is configured in api/handler, and use same configuration in your test.
Try like this, please. Here is the example class:
class AngilinaJoile {
private String name;
// setter
// getter
}
And here is how you deserialize it with Gson:
Gson gson = new Gson();
String jsonInString = "{'name' : 'kumaresan perumal'}";
AngilinaJoile angel = gson.fromJson(jsonInString, AngilinaJoile.class);

Map two ArrayList with different sizes

For Example:
ArrayList1 = {userid1, userid2, userid1, userid4, userid1, userid3, userid2, userid4, userid4, userid4, userid2};
ArrayList2 = {username1, username2, username3, username4};
Mapping these two array so that whenever I call ArrayList1.get(0).getUserName(), it should provide me with username1.
public class User {
String username;
public User(String username)
{
this.username = username;
}
/**
* #return the username
*/
public String getUsername() {
return username;
}
/**
* #param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
}
userid1, userid2... must be User objects
User userid1 = new User("username1");
User userid2 = new User("username2");
Initialize all the user objects
ArrayList1 = {userid1, userid2, userid1, userid4, userid1, userid3, userid2, userid4, userid4, userid4, userid2};
Then you can call
String username = ArrayList1.get(0).getUserName();
this will return username1
There is a better way to do that and that is by using HashMap:
//create your custom object which will be mapped
public class User{
public String userId;
public String userName;
}
ArrayList<String> userKeys = new ArrayList<String>();
HashMap<String, User> users = new HashMap<String, User>();
Now using a userKey, you can access its corresponding userData;
Example:
User user = users.get("yourKey");
I think you should use :
List<List<T>> = ArrayList<ArrayList<T>>;
T is the class of you UserName.
Use HashSet instead of arraylist. Set does not allow duplicate.

Categories

Resources