I have a json file with users, each users has email
and password
and corresponding POJO exist to deserialize them.
However, I want to add users at will, and create a method to find them by their description, let's say this is my json:
{
"user1": {
"email": "[email protected]",
"password": "qwe123",
},
"user2": {
"email": "[email protected]",
"password": "abc123",
},
...
"userX": {
"email": "[email protected]",
"password": "omg123",
}
}
This is my POJO:
public record User(String email, String password) {}
I dont want to create superPOJO and add each user as I create them.
I would like to create method that would read my json, and returned the User
object based on String input.
For now I created users in array and get them using their index, but now situation requires giving users "nicknames" and getting them by their nickname.
Now I am keeping user like this:
[
{
"email": "[email protected]",
"password": "xxx111",
},
{
"email": "[email protected]",
"password": "yyy222",
}
]
This is my current method:
public User getPredefinedUser(int index) throws IOException {
return Parser.deserializeJson(getUserFile(), User[].class)[index];
}
where Parser#deserializeJson()
is:
public <T> T deserializeJson(String fileName, Class<T> clazz) throws IOException {
return new ObjectMapper().readValue(Utils.reader(fileName), clazz);
}
And Utils.reader
just brings file from the classpath.
I would like a method like this:
public User getPredefinedUser(String nickname) throws IOException {
return Parser.deserializeJson(getUserFile(), User.class);
}
and when calling this method with parameter nickname
of user2
I'd get User
object with fields: email [email protected]
and password abc123
CodePudding user response:
Given your input json is an object (map) of User-like objects:
{
"user1": {
"email": "[email protected]",
"password": "qwe123",
},
"user2": {
"email": "[email protected]",
"password": "abc123",
},
...
"userX": {
"email": "[email protected]",
"password": "omg123",
}
}
then you should be able to deserialize it into a (Hash)Map of Users:
public <T> T deserializeJson(String fileName, Class<T> clazz) throws IOException {
return new ObjectMapper().readValue(Utils.reader(fileName), new TypeReference<HashMap<String, clazz>>(){});
}
and then use it like so:
public User getPredefinedUser(String nickname) throws IOException {
return Parser.deserializeJson(getUserFile(), User.class).get(nickname);
}
(Although you probably want to parse once and store that somewhere, not parse every time).
Note, I'm doing this from memory, my java syntax may be a bit off, but I think this demonstrates the principle well...
CodePudding user response:
After putting some thought into my own problem I decided to do it like this:
I am using com.googlecode.json-simple
- JSON.simple as well as com.fasterxml.jackson.core
- Jackson Databind.
I used helper function from Parser
class where PARSER
is new JSONParser()
:
public JSONObject toJsonObject(String fileName) throws IOException, ParseException {
return ((JSONObject) PARSER.parse(Utils.reader(fileName)));
}
Then parsed whole user file, while getting interesting user and converting all toString()
Parser.toJsonObject(USER_FILE).get(nickname).toString()
I wrapped it all together in method I wanted (that searches by nickname) and everything works fine, I get desired User
object in the end:
public User getSpecificUser(String nickname) throws IOException, ParseException {
return Parser.parseJson(Parser.toJsonObject(USER_FILE).get(nickname).toString(), User.class);
}
And now the test:
@Test(groups = Group.TEST)
public void jsonTest() throws IOException, ParseException {
User user = Utils.getSpecificUser("user2");
log.warn(user.email());
log.warn(user.password());
}
output is:
2022-11-23 T 00:56:55.391 0100 [28][WARN] tests.smoke.SmokeTest->jsonTest [email protected]
2022-11-23 T 00:56:55.391 0100 [28][WARN] tests.smoke.SmokeTest->jsonTest abc123