I want to create serialization policy, that would decode fields in objects which are passwords. If the field's name contains 'password' I would like GSON to use my defined encryption alghoritm. I tried to extend TypeAdapter and plug it to GsonBuilder, but then I loose all functionality from TreeTypeAdapter. Any ideas?
I have something like this but I need to do all the work from TreeTypeAdapter myself:
public class PasswordStringAdapter extends TypeAdapter<String> {
#Override
public void write(JsonWriter out, String value) throws IOException {
String keyName = getKeyName(out);
}
private String getKeyName(JsonWriter writer) {
try {
Field name = writer.getClass().getDeclaredField("deferredName");
name.setAccessible(true);
String fieldName = (String) name.get(writer);
//if field name contains password then encode it
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
It tured out that after decoding my password I just need to do:
out.value(value);
Please comment if you have better ideas how to do that.
Related
I mean, this is what i have in my code:
#GetMapping("/get/player/{csvName}")
public void loadPlayers(#PathVariable String csvName) {
/*Irrelevant code here*/
}
This works just because the csv file is in the root of my project.
Is there any way to set the relative path of the csv file on the url?
////////////////////////////////////////////////////EDIT///////////////////////////////////////////////////////
Here is the code of the class:
#RestController
#RequestMapping("/csv")
public class CsvController {
private static final Logger log = LoggerFactory.getLogger(FutbolApplication.class);
#Autowired
private PlayerRepository playerRepository;
#Autowired
private TeamRepository teamRepository;
#Autowired
private MembershipRepository memberRepository;
#GetMapping("/get/player/{csvName}")
public void loadPlayers(#PathVariable String csvName) {
CSVReader reader;
try {
reader = new CSVReaderBuilder(new FileReader(csvName))
.withSkipLines(1).build();
String[] values;
int i;
int count=0;
while ((values = reader.readNext()) != null) {
count++;
i=0;
try {
Player player = new Player(values[i++],values[i++],values[i++],Date.valueOf(values[i++]));
System.out.println(player.getName() + "//" + player.getSurname() + "//" + player.getPosition()
+ "//" + player.getBirthDate());
playerRepository.save(player);
}catch (Exception e) {
log.error("ERROR INTENTANDO ASIGNAR LOS DATOS AL JUGADOR "+(count));
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CsvValidationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
What I can to, is to insert the path of the csv instead of just the name.
At the moment my project's structure is:
>project
>src
>main
>test
>.Settings
>mycsvfile.csv
that's why i can just type "mycsvfile.csv" in the url and it works
But this is what i'd like to get:
>project
>src
>main
>test
>.Settings
>csvs
>mycsvfile.csv
And get it to work by typing "/csvs/mycsvfile.csv"
Because now i just can type "https:localhost:8080/csv/get/player/mycsvfile.csv"
Is it possible?
Use #RequestParam instead of #PathVariable.
If I understood correctly, you want to send the path of the file, you want to load your Player from, via the request.
Sending a file path in the URI won't work from the get go as it will change the path of the request and it will lead to a 404 NOT FOUND.
Using #RequestParam is a different story, you can add full file path there.
#GetMapping("/get/player")
public void loadPlayers(#RequestParam String csvName) {
/*Rest of your code here*/
}
This way your request would look like this:
https://localhost:8080/csv/get/player?csvName=csvs/mycsvfile.csv
If you really want to use #PathVariable to send the path of your file, then you will have to change your endpoint to work with wildcard and extract the file path from the request URI like explained by N. Chicoine here.
And if you need to use this in multiple places you can even get a more elegant solution by implementing an annotation that makes use of the HandlerMethodArgumentResolver interface:
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
public #interface FilePath {
class Resolver implements HandlerMethodArgumentResolver {
private final PathMatcher pathMatcher;
public Resolver() {
this.pathMatcher = new AntPathMatcher();
}
#Override
public boolean supportsParameter(MethodParameter methodParameter) {
Annotation annotation = methodParameter.getParameterAnnotation(FilePath.class);
return annotation != null;
}
#Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modeContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
if (servletRequest == null) {
return null;
}
String patternAttribute = (String) servletRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
String mappingAttribute = (String) servletRequest.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
return this.pathMatcher.extractPathWithinPattern(patternAttribute, mappingAttribute);
}
}
}
Then you will have to register the annotation in application configuration:
#Configuration
public class Config implements WebMvcConfigurer {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new FilePath.Resolver());
}
}
And finaly you can use it like this:
#GetMapping("/get/player/**")
public void loadPlayers(#FilePath String csvName) {
/*Rest of your code here*/
}
Enabling you to execute the request like:
https://localhost:8080/csv/get/player/csvs/mycsvfile.csv
Hope this will help you.
I really hate to do this, but I have two questions: can Jackson 2.7.3 parse the following url and can do I have to parse every part of the JSON?
Here is the code I am working with so far:
public class Song {
private String tracks;
private String album;
private String images;
public void setTracks(String tracks){
this.tracks=tracks;
}
public void setAlbum(String album){
this.album= album;
}
public void setImages (String images){
this.images= images;
}
}
And
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
ObjectMapper mapper = new ObjectMapper();
Document doc = Jsoup.connect("http://api.spotify.com/v1/search?q=track:" + finalSong + "%20artist:" + finalArtist+"%20" + "&type=track").ignoreContentType(true).get();
String title = String.valueOf(doc.body().text());
Song obj = mapper.readValue(String.valueOf(title), Song.class);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
return null;
}
All I need is the "preview_url" and one of the "images" url towards the top
the JSON is located at https://api.spotify.com/v1/search?q=track:Ready%20To%20Fall%20artist:rise%20against%20&type=track.
Do you necessary need to map your Json response into a class?
If not you can get your desired values as following e.g. for preview_url
You can use readTree to map the json result into a tree of nodes.
There after you can use findPath to search for the property you looking for.
In the case of image it contains an array. Thus if you want to select a specific item from that list you get use get to select the specific item you want.
example
JsonNode readTree = mapper.readTree(body);
for (JsonNode node : readTree.findPath("items")) {
System.out.println(node.findPath("images").get(2));
System.out.println(node.findPath("preview_url"));
}
Can you please help me to solve this problem. Here I'm storing some data to Datastore with JDO Interface using AJAX call. I'm storing the data to datastore and Retrieving it immediately. While Retrieving some times it returns NULL as a response(Its not always returning NULL. Only some times it returning NULL). Can you please help me to fix this. The below given code is used to store and retrieve the data
This code for Storing the data,
public void saveSchedule(String listName, String email, String date, String time, String details, String name)
{
Date hiredate = new Date();
String gmtdate = hiredate.toGMTString();
Schedule schedule = new Schedule();
schedule.setName(name);
schedule.setListName(listName);
schedule.setEmail(email);
schedule.setDate(date);
schedule.setDateGMT(gmtdate);
schedule.setDetails(details);
schedule.setTime(time);
p = PMF.get().getPersistenceManager();
try
{
p.makePersistent(schedule);
}
catch(Exception e)
{
System.out.println(e);
}
finally
{
p.close();
}
}
This code for Retrieving the data,
public String savedDataRetrive(String details, String email) {
p = PMF.get().getPersistenceManager();
Query q = p.newQuery(Schedule.class);
q.setFilter("details == '"+details+"' && email == '"+email+"'");
List<Schedule> sch = (List<Schedule>) q.execute();
String data = null;
ObjectMapper n=new ObjectMapper();
try {
data = n.writeValueAsString(sch);
} catch (JsonGenerationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
p.close();
}
return data;
}
The Datastore replicates data across multiple datacenters. This provides a high level of availability for reads and writes, however, most queries are eventually consistent.
Eventual consistency is a consistency model used in distributed
computing to achieve high availability that informally guarantees
that, if no new updates are made to a given data item, eventually all
accesses to that item will return the last updated value.
This is most likely the reason why your query sometimes returns nothing.
I would recommend you to go through Structuring Data for Strong Consistency article.
Here is a useful example:
https://github.com/mattburns/OddPrints/blob/master/op-gae/src/com/oddprints/servlets/Edit.java#L89
#GET
#Path("/basic/sample")
#Produces(MediaType.TEXT_HTML)
public Viewable loadBasicSample(#Context HttpServletRequest req)
throws FileUploadException, IOException, URISyntaxException {
return viewSampleImage(req, Settings.SAMPLE_PHOTO_BLOB_KEY,
Settings.SAMPLE_PHOTO_BLOB_SIZE, new URL(
"http://www.oddprints.com/images/sample.jpg"));
}
Viewable viewSampleImage(HttpServletRequest req, Settings blobKeySetting,
Settings blobSizeSetting, URL image) throws MalformedURLException,
IOException {
String blobKeyString = ApplicationSetting.getSetting(blobKeySetting);
if (blobKeyString == null) {
InputStream imgStream = image.openStream();
byte[] bytes = IOUtils.toByteArray(imgStream);
BlobKey blobKey = ImageBlobStore.INSTANCE.writeImageData(bytes);
blobKeyString = blobKey.getKeyString();
ApplicationSetting.putSetting(blobKeySetting, blobKeyString);
ApplicationSetting.putSetting(blobSizeSetting, "" + bytes.length);
}
String blobSize = ApplicationSetting.getSetting(blobSizeSetting);
req.getSession().setAttribute("blobKeyString", blobKeyString);
req.getSession().setAttribute("blobSize", blobSize);
req.getSession().setAttribute("basicMode", Boolean.TRUE);
return viewBasic(req);
}
I would recommend to use memcache, that way the fetch will be faster, and you will have less null objects in return IMO.
I am trying to use Jackson JSON take a string and determine if it is valid JSON. Can anyone suggest a code sample to use (Java)?
Not sure what your use case for this is, but this should do it:
public boolean isValidJSON(final String json) {
boolean valid = false;
try {
final JsonParser parser = new ObjectMapper().getJsonFactory()
.createJsonParser(json);
while (parser.nextToken() != null) {
}
valid = true;
} catch (JsonParseException jpe) {
jpe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return valid;
}
Although Perception's answer probably will fit many needs, there are some problems it won't catch, one of them is duplicate keys, consider the following example:
String json = "{ \"foo\" : \"bar\", \"foo\" : \"baz\" }";
As a complement, you can check for duplicate keys with the following code:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
objectMapper.readTree(json);
It throws JsonProcessingException on duplicate key or other error.
With Jackson I use this function:
public static boolean isValidJSON(final String json) throws IOException {
boolean valid = true;
try{
objectMapper.readTree(json);
} catch(JsonProcessingException e){
valid = false;
}
return valid;
}
I would recommend using Bean Validation API separately: that is, first bind data to a POJO, then validate POJO. Data format level Schemas are in my opinion not very useful: one usually still has to validate higher level concerns, and schema languages themselves are clumsy, esp. ones that use format being validated (XML Schema and JSON Schema both have this basic flaw).
Doing this makes code more modular, reusable, and separates concerns (serialization, data validation).
But I would actually go one step further, and suggest you have a look at DropWizard -- it integrates Jackson and Validation API implementation (from Hibernate project).
private boolean isValidJson(String json) {
try {
objectMapper.readTree(json);
} catch (JsonProcessingException e) {
return false;
}
return true;
}
Another option would be using java.util.Optional in Java 8. This allows to return an object and to use in the calling code a more functional approach.
This is another possible implementation:
public Optional<JsonProcessingException> validateJson(final String json) {
try{
objectMapper.readTree(json);
return Optional.empty();
} catch(JsonProcessingException e){
return Optional.of(e);
} catch(IOException e) {
throw new RuntimeException(e);
}
}
Then you can use this method like this:
jsonHelper.validateJson(mappingData.getMetadataJson())
.map(e -> String.format("Error: %s at %s", e.getMessage(), e.getLocation().toString()))
.orElse("Valid JSON");
Inproving the other answers
public static boolean isValidJSON(final String json) throws IOException {
boolean valid = true;
try{
mapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
mapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
objectMapper.readTree(json);
} catch(JsonProcessingException e){
valid = false;
}
return valid;
}
I am starting out on Restful web services and learning through JSON google gson. Though till now i have just made my server producer and json consumer application.
and i am loving it.
Now this is my consumer code: it has a TextMessages class object message
private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
InputStreamReader reader = null;
String name = nameTextfield.getText();
String url = "http://myurl/" + name;
try {
try {
reader = new InputStreamReader(new URL(url).openStream());
} catch (MalformedURLException ex) {
Logger.getLogger(StartClient.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException ex) {
Logger.getLogger(StartClient.class.getName()).log(Level.SEVERE, null, ex);
}
TextMessages message = new Gson().fromJson(reader, TextMessages.class);
JOptionPane.showMessageDialog(this, message.getMessage(), "Welcome" + message.sumAllIntegers(),
JOptionPane.INFORMATION_MESSAGE);
}
// class TextMessages
package use;
public class TextMessages{
private String message;
private int a,b,c,d,wee;
public TextMessages(String __message){
message = __message;
}
public TextMessages(){
}
public String getMessage(){
return message;
}
public void setMessage(String __message){
message = __message;
}
}
Now server is sending JSON of class OtherTestMessage
public class TextMessage {
private String message;
//getter and setter functions
// no int a,b
.....
Why is it working right ? Shoule it be working right ? is it again languages philosophy? how does JSON convert things. Or is it donot ? Just copying data ?
The gson library is looking at the JSON and mapping what it can to the class you provide.
Both of your classes have a String called message in them. gson is taking the message element in the JSON and storing the value in both cases. In your TextMessages class, it will also store the values for a, b, etc if those elements are present in the JSON.
In the case of your TextMessage class that only has String message, the additional elements in the JSON (a,b, etc) are silently ignored if they are present.