How do I get an object from a String - java

I am working on a project, where users can write other users mails. The mail-class looks currently like this:
public class Mail
{
/*
* Fields
*/
private final String _content;
private final String _sender;
private final String _date;
private final String _topic;
/**
* Constructor of the Mail-class.
*
* #param mail The mail as a string representation.
*/
public Mail(String mail)
{
_content = ...;
_sender = ...;
_date = ...;
_topic = ...;
}
// And all the getters.
#Override
public String toString()
{
// Make the reperentation as a String
}
Now, the problem is, that I need to save all the mails into a .yml userdata file. For me, the simplest way to do this is to firstly convert every mail to a String and then save all mails into a List<String> mails which will be written directly into the .yml where I can access and read the list of String with ease. Now, once I start the server, all mails should be converted back into the object-representation. The question is, how can I save the mail-Object as a String and load it, that I can operate using those mail objects.
My first ideas were something like this sender#date#topic#content and then splitting the String via String.split("#");. But when I do this, I need to ban the # character for the content and the topic. The date and the username will never contain #. I don't want to ban any character. Unfortunately I have nothing found on my researches so far on how to solve this task.

The best thing to do is use XML or JSON to markup the object and convert it to a string for you. There are tons of libraries you can use to do that. They all operate in roughly the same manner: add an annotations to your fields and class.

Related

How to convert flat key-value file to a bean object dynamically?

I'd like to convert a flat file with many different keys to a java bean dto, as follows:
Flat file:
mykey=example
anotherkey=test
adress-street-1=downtown street
address-town-1=nyc
address-stree-2=some street
adrerss-town-2=los angeles
Target bean:
public class Content {
private String mykey;
private String anotherkey;
private List<Address> address;
}
public class Address {
private String street,
private String town;
}
Question: how could I achieve the mapping between the flat file and the target bean? Imagine a few hundred property keys. Some may occur multiple times, in whose cases they and with an index number, like address-town-1.
Content content = new Content();
while(true) {
String line = reader.readLine();
String key = line.split("=")[0];
String value = line.split("=")[1];
switch(key) {
case "mykey": content.setMykey(value);
case "anotherkey": content.setAnotherkey(value);
...
}
}
But I would have to code those mappings a few hundred times, which does not feel right.
Question: is there a better way, eg by using some kind of xml configuration/mapping file, and reflection?
BeanIO comes close to what I want to achieve. But it lacks the ability to just convert multiple different fields to the bean field name. And also it cannot group sets like the address-* example into a List.
Is there any known library or concept that I could use? Some framework that could do the formatting, using eg a xml configuration file?
Or would I have to write my own parser and use reflection to write the data to my java objects?

Is it possible to store pathparams as a list?

I have a Rest Service that I want to respond to requests with the following paths
1) /v1/config/type/service
2) /v1/config/type/service, service2
What I'd like is to be able to store the path param serviceName as a List where each element is delimited by a comma. For example, if someone types v1/config/foo/bar1,bar2,bar3 I'd like serviceName to be a List with 3 elements (bar1, bar2, bar3). Right now it just returns a list with 1 element that contains all three service strings. Is that even possible? Or is that something I'll simply have to parse. The code I have is shown below, it's pretty rough as I'm in the beginning stages of the project:
#ApplicationPath("/")
#Path("/v1/config")
public class ServiceRetriever extends Application {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getHelloWorld() {
return "Hello World";
}
#GET
#Path("{type}/{serviceName}")
#Produces("application/zip")
public Response getServices(#PathParam("type") String type, #PathParam("serviceName")List<String> serviceNames,
#QueryParam("with_config") boolean withConfig, #QueryParam("with_drive") boolean withDriver) throws IOException
{
//some random file i made to test that we can return a zip
File file = new File(System.getProperty("user.home")+"/dummy.zip");
System.out.println(serviceNames.size()); //returns 1
//we can change the zip file name to be whatever
return Response.ok(file).header("Content-Type","application/zip").
header("Content-Disposition", "attachment; filename="+file.getName()).build();
}
The problems is that you have to alter the deserialization process of that variable. Typically only query parameters are lists so this might not be compatible with some libraries.
You could:
Capture the parameter as a string and parse it internally via helper method (obvious)
Create your own annotation like #PathParamMutli and return Arrays.asList(parameter.split(","));. Ideally you should have access to the framework source code and branching privileges.
Use a query parameter instead

How to convert arbitrary JSON into a usable structure in Java

I'm trying to use gson to convert this returned JSON into some kind of
data structure such that I can extract useful data.
For Example:
http://search.twitter.com/search.json?q=test&rpp=1
Returns:
{
"completed_in":0.028,
"max_id":196386333906837504,
"max_id_str":"196386333906837504",
"next_page":"?page=2&max_id=196386333906837504&q=test&rpp=1",
"page":1,
"query":"test",
"refresh_url":"?since_id=196386333906837504&q=test",
"results":[
{
"created_at":"Sat, 28 Apr 2012 23:52:05 +0000",
"from_user":"della_ky",
"from_user_id":525641596,
"from_user_id_str":"525641596",
"from_user_name":"kydella modeste",
"geo":null,
"id":196386333906837504,
"id_str":"196386333906837504",
"iso_language_code":"en",
"metadata":{
"result_type":"recent"
},
"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2159990525\/webcam-toy-photo3_20_2__normal.jpg",
"profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2159990525\/webcam-toy-photo3_20_2__normal.jpg",
"source":"<a href="http:\/\/mobile.twitter.com" rel="nofollow">Mobile Web<\/a>",
"text":"RT #Y__U__NOOO: #SongsIKnowOffByHeart ALL SONGS I LISTEN TO. BRAIN, Y U NO REMEMBER TEST ANSWERS LIKE THAT?!?",
"to_user":null,
"to_user_id":null,
"to_user_id_str":null,
"to_user_name":null
}
],
"results_per_page":1,
"since_id":0,
"since_id_str":"0"
}
Ultimately, I would like to be able to output a list of tweets with the
name of the sender and the date/time of the tweet.
I have read through the gson documentation but it's going over my head
to be honest - lots of new concepts there for me.
Do I need to define a class which maps exactly to the structure of the
JSON in order to then populate an instance of that class? If so this
seems very inflexible/laborious. Ideally I'm looking for something
which will handle JSON in any form and give me a structure I can use
automatically...
Is anyone able to give me some pointers? Being new to this - the more
detailed and in words of the fewest syllables the better!
Update - Thanks to the responses I've already had on this I've had a go at putting a class together to capture the twitter JSON. However, since the JSON has an embedded ArrayList of Objects I'm struggling a bit... So far I have
public class tweetData {
private double completed_in;
private long max_id;
private long max_id_str;
private String next_page;
private int page;
private String query;
private String refresh_url;
private List<tweetDetails> tweets = new ArrayList<tweetDetails>();
}
and
public class tweetDetails {
private String created_at;
private String from_user;
private long from_user_id;
private long from_user_id_str;
private String from_user_name;
private String geo;
private long id;
private long id_str;
private String iso_language_code;
// "metadata":
// {
// "result_type":"recent"
// },
private String profile_image_url;
private String profile_image_url_https;
private String source;
private String text;
private String to_user;
private String to_user_id;
private String to_user_id_str;
private String to_user_name;
}
Which I'm instantiating with
URI uri = new URI("http", "search.twitter.com", "/search.json", "q="+ searchTerms + "&rrp=" + RRP, null);
URL twitterSearch = uri.toURL();
URLConnection yc = twitterSearch.openConnection();
JsonReader reader = new JsonReader(new InputStreamReader(yc.getInputStream()));
Gson gson = new Gson();
tweetData data = gson.fromJson(reader, tweetData.class);
System.out.println(data);
The basic name:values are being populated correctly but the ArrayList is not.
tweetData : 0.17196614959919140865196614959919140865?page=2&max_id=196614959919140865&q=test1test?since_id=196614959919140865&q=testSIZE 0[]
So, I'm still struggling a bit - any more tips hugely appreciated!
Tia,
Tom
Do I need to define a class which maps exactly to the structure of the JSON in order to then populate an instance of that class? If so this seems very inflexible/laborious.
Yes. GSON is a library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. This is really powerful because you can automagically instantiate your Java objects from the JSON representation. Assuming your JSON doesn't change its structure, you only have to define the appropriate Java object representation once.
Ideally I'm looking for something which will handle JSON in any form and give me a structure I can use automatically...
However, if you don't want automagical serialisation/deserialisation, then try looking at a simpler library such as java.net/projects/jsonp.
You can extract stuff from it just by querying the keys:
final JSONObject json = new JSONObject(theJsonString);
final String id = json.getString("max_id");
final JSONArray results = json.getJSONArray("results");
final String user = results.getJSONObject(2).getString("from_user");
Gson actually does all the serialization for you. So yes, you would have to write the classes yourself. To you, this seams inflexible and laborious, but that's only because that library isn't made for what you're asking for (it doesn't parse 'arbitrary' JSON).
I would suggest at least considering writing the classes and using gson. The reason I say that is because either way your application's logic will have to expect a very specific format, and writing out that format in a Java class will make things tidier. Here's a nice guide that will help you get started that way.
If you want to simply decode the JSON without serializing it into a Java class (IMHO the only way to use 'arbitrary' JSON), you'll want to use another library. Try this one. It allows you to decode the JSON, and use it by getting values from it (as described in this question: Convert a JSON string to object in Java ME?).
There are some tools that do gson to schema mapping. You give some sample JSON responses, and the java classes to access them are created for you.
http://www.jsonschema2pojo.org/
Gson is a slick beast!
Or at least it became so over the years that have passed since the question had been asked.
You can pass it an Object.class as a second parameter to the fromJson() method and it will parse your Json into a reasonable structure of LinkedTreeMaps and ArrayLists.
Object result = (new Gson()).fromJson(jsonString, Object.class)
More than that, you can really do partial parsing and leave loose ends at any level of your object structure by defining a certain field as Object!
Gson will then parse Json into your structure and your field of type Object will contain the above mentioned structure of LinkedTreeMaps and ArrayLists.
E.g., you may define a class
Person {
String name;
Object details;
}
(Imagine, you care mostly about the person's name but may want the details also somewhere. To log them, for instance.)
Then you can pass the following Json to the fromJson(input, Person.class) method as a first parameter
{
"name": "Carlsson",
"details": {
"address": "Stockholm",
"phones": [
"work": "233-322-233-322",
"home": "none"
]
}
}
The result will have the name field filled with "Carlsson" string and details field will contain a LinkedTreeMap with keys "address" and "phones", etc.

Determining a String based on the value of another String?

Not all that sure how I would describe this question, so I'll jump right into the example code.
I have a Constants.java
package com.t3hh4xx0r.poc;
public class Constants {
//RootzWiki Device Forum Constants
public static final String RWFORUM = "http://rootzwiki.com/forum/";
public static final String TORO = "362-cdma-galaxy-nexus-developer-forum";
public static String DEVICE;
}
In trying to determine the device type, I use this method.
public void getDevice() {
Constants.DEVICE = android.os.Build.DEVICE.toUpperCase();
String thread = Constants.(Constants.DEVICE);
}
Thats not correct though, but thats how I would think it would have worked.
Im setting the Constants.DEVICE to TORO in my case on the Galaxy Nexus. I want to then set the thread String to Constants.TORO.
I dont think I'm explaining this well, but you shoudl be able to understand what I'm trying to do fromt he example code. I want
Constants.(VALUE OF WHAT CONSTANTS.DEVICE IS) set for the String thread.
Another way to put it,
I want to get Constants.(//value of android.os.Build.DEVICE.toUpperCase())
I apologies for the poorly worded question, i dont know of any better way to explain what Im trying to achieve.
Im trying to determine the thread based on the device type. I could go in and do an
if (Constants.DEVICE.equals("TORO"){
String thread = Constants.TORO;
}
But I plan on adding a lot more device options in the future and would like to make it as easy as adding a string to the Constants.java rather than having to add another if clause.
I would suggest using an enum instead of just strings - then you can use:
String name = android.os.Build.DEVICE.toUpperCase();
// DeviceType is the new enum
DeviceType type = Enum.valueOf(DeviceType.class, name);
You can put the value of the string in a field for the enum, and expose it via a property:
public enum DeviceType {
RWFORUM("http://rootzwiki.com/forum/"),
TORO("362-cdma-galaxy-nexus-developer-forum");
private final String forumUrl;
private DeviceType(String forumUrl) {
this.forumUrl = forumUrl;
}
public String getForumUrl() {
return forumUrl;
}
}
(I'm guessing at the meaning of the string value - not a great guess, but hopefully it gives the right idea so you can make your actual code more meaningful.)
EDIT: Or to use a map:
Map<String, String> deviceToForumMap = new HashMap<String, String>();
deviceToForumMap.put("RWFORUM", "http://rootzwiki.com/forum/");
deviceToForumMap.put("TORO", "362-cdma-galaxy-nexus-developer-forum");
...
String forum = deviceToForumMap.get(android.os.Build.DEVICE.toUpperCase());
You can use reflection:
Constants.DEVICE = android.os.Build.DEVICE.toUpperCase();
String thread = (String) Constants.class.getField(Constants.DEVICE).get(null);
Not sure I've understood the question properly, but I feel that it's a right place to use a Map. The outcome will be something like this:
HashMap<String, String> map;
map.put(TORO, DEVICE);
Constants.DEVICE = android.os.Build.DEVICE.toUpperCase();
String thread = map.get(Constants.DEVICE);
Sorry for a possible misunderstanding or your question, but I hope you've got the idea.
P.S. You can find more info about Maps in the Java documentation: Map, HashMap.

Add arbitrary word to URL?

So I'm trying to take the source of the gv4me app, and modify it. I have this filter I have to get around, and the way to get past it is to put a certain keyword(lets say it's "foobar") in whatever URL you're trying to access. So I've got the source compiled and such, but I can't figure out how to add this word in properly. So far, adding it to the post doesn't work. These are the URLs that gv4me uses:
private static final String rnrURL = "https://www.google.com/voice/m/i/voicemail?p=1000";
private static final String clientLoginURL = "https://www.google.com/accounts/ClientLogin";
private final String callURL = "https://www.google.com/voice/call/connect";
private static final String markReadURL = "https://www.google.com/voice/m/mark?p=1&label=unread&id=";
private static final String getMsgsURL = "https://www.google.com/voice/inbox/recent/unread";
private static final String textURL = "https://www.google.com/voice/sms/send";
private static final String replyURL = "https://www.google.com/voice/m/sendsms";
I need to modify each of these URLs so they have "foobar" in them, but still link to the same page. Is this possible?
EDIT: Also, if you search for HandlerUI on google, you'll find a plethora of applications(closed and open source) modified to include a user interface for automatically modifying all connection attempts of said applications. However, the creator is fairly difficult to locate, so I was wondering if anyone knew how to do this?
EDIT2: It seems that adding a query string variable doesn't seem to work. What I think would most likely work, is to somehow replace www.google.com with foobar.freednsredirectservice.com. Does anyone know of anything similar to this? Something that would allow foobar.freednsredirectservice.com/voice to still work?
Try adding a query string parameter. This may not, but usually will work.
For example:
http://www.example.com/ -> http://www.example.com/?foobar
http://www.example.com/page?existing=value -> http://www.example.com/page?foobar&existing=value
Your question is unclear as to where the foobar should go, but let's assume it's after the host name, ie
"https://www.google.com/voice/sms/send" --> "https://www.google.com/foobar/voice/sms/send"
Use this:
String url = "https://www.google.com/voice/sms/send";
url = url.replaceFirst("(?<=[^:/]/)", "foobar/");
System.out.println(url); // https://www.google.com/foobar/voice/sms/send
If the foobar replaces the hostname, ie
"https://www.google.com/voice/sms/send" --> "https://foobar/voice/sms/send" use this:
Use this:
String url = "https://www.google.com/voice/sms/send";
url = url.replaceAll("//.*?/", "//foobar/");
System.out.println(url); // https://foobar/voice/sms/send
I would say no because then it would be a link is an adress and a different adress leads to a different place. What you could do is something like this:
String[] url = new String[2];
url[0] = "http://www.yoururl.com/";// Accual url
url[1] = url[0].replaceFirst("(?<=[^:/]/)", "foobar/");// For other purpose such as diplay

Categories