I have a 3-level nested Java POJO that looks like this in the schema file:
struct FPathSegment {
originIata:ushort;
destinationIata:ushort;
}
table FPathConnection {
segments:[FPathSegment];
}
table FPath {
connections:[FPathConnection];
}
When I try to serialize a Java POJO to the Flatbuffer equivalent I pretty much get "nested serialzation is not allowed" error every time I try to use a common FlatBufferBuilder to build this entire object graph.
There is no clue in the docs to state if I have a single builder for the entire graph? A separate one for every table/struct? If separate, how do you import the child objects into the parent?
There are all these methods like create/start/add various vectors, but no explanation what builders go in there. Painfully complicated.
Here is my Java code where I attempt to serialize my Java POJO into Flatbuffers equivalent:
private FPath convert(Path path) {
FlatBufferBuilder bld = new FlatBufferBuilder(1024);
// build the Flatbuffer object
FPath.startFPath(bld);
FPath.startConnectionsVector(bld, path.getConnections().size());
for(Path.PathConnection connection : path.getConnections()) {
FPathConnection.startFPathConnection(bld);
for(Path.PathSegment segment : connection.getSegments()) {
FPathSegment.createFPathSegment(bld,
stringCache.getPointer(segment.getOriginIata()),
stringCache.getPointer(segment.getDestinationIata()));
}
FPathConnection.endFPathConnection(bld);
}
FPath.endFPath(bld);
return FPath.getRootAsFPath(bld.dataBuffer());
}
Every start() method throws a "FlatBuffers: object serialization must not be nested" exception, can't figure out what is the way to do this.
You use a single FlatBufferBuilder, but you must finish serializing children before starting the parents.
In your case, that requires you to move FPath.startFPath to the end, and FPath.startConnectionsVector to just before that. This means you need to store the offsets for each FPathConnection in a temp array.
This will make the nesting error go away.
The reason for this inconvenience is to allow the serialization process to proceed without any temporary data structures.
For my Java application I am trying to use ScalaCheck to write some property-based unit tests. For that purpose I need generators, but all the tutorials I can find use a constructor with parameters to generate objects.
The object I need to generate does not have constructor parameters, and I cannot add such a constructor since it is from an external library.
I now have the following (JwtClaims is from the package org.jose4j.jwt):
def genClaims: Gen[JwtClaims] = {
val url = arbString
val username = arbString
val claims = new JwtClaims()
claims.setNotBeforeMinutesInThePast(0)
claims.setExpirationTimeMinutesInTheFuture(60)
claims.setSubject(username) // error about Gen[String] not matching type String
claims
}
Any suggestions on how to write my generator? I have zero knowledge of Scala, so please be patient if I've made an 'obvious' mistake :) My expertise is in Java, and testing using ScalaCheck is my first venture into Scala.
You need to be returning a generator of a claims object, not a claims object. The generator is effectively a function that can return a claims object. The normal way I go about this is with a for comprehension (other people prefer flatMap, but I think this reads more clearly).
def genClaims: Gen[JwtClaims] = {
for {
url <- arbitrary[String]
username <- arbitrary[String]
} yield {
val claims = new JwtClaims()
claims.setNotBeforeMinutesInThePast(0)
claims.setExpirationTimeMinutesInTheFuture(60)
claims.setSubject(username)
claims
}
}
First of all I am new to Java programming and object oriented style programming. I started learning it on January this year.
Basically i have a class name vehicleInformation with some local variable.
Then I i prompt the information in the client side and then store it in a object vehicleInformation. Then pass the object to the server side. My instruction is to insert the data in the object to the database. My question is how do i access to the data in the object when it is pass from the client side.
the code below show how i create the object and send it to the server.
vehicleInformation v = new vehicleInformation(plateNumber,vehicleType, engineNumber, chassisNumber, make, model);
toServer.writeObject(v);
the code below is how i read the object but I have no idea how to access to the variable in the obect as we normally use objectName.variable to access it.
Object object = inputFromClient.readObject();
To be safe you should check the type of the object before the typecast.
if (object instanceof VehicleInformation) {
vehicleInformation = (VehicleInformation) object;
}
else {
// Do something with the unexpected object type. e.g. throw an exception.
...
}
You can typecast
VehicleInformation vehicleObject = (VehicleInformation)inputFromClient.readObject();
Cast your object to vehicleInformation.
vehicleInformation objectname = (vehicleInformation)inputFromClient.readObject();
and get variable objectname.variable
And follow class naming convention for better visibility.
I'm relying on an old Java API that kinda sucks and loves to throw null pointer exceptions when data is missing. I want to create a subclass that has option type accessors but preserves the old accessors until I decide I need to create safe accessors for them. Is there a good way to create a subclass from a copy of the original object? I'd like to achieve something like the following:
SafeIssue extends Issue {
def safeMethod: Option[Value] = { //... }
}
val issue = oldapi.getIssue()
val safeIssue = SafeIssue(issue)
//Preserves issue's methods and data if I need them
val unsafeVal = safeIssue.unsafeMethod
val maybeVal = safeIssue.safeMethod
Why not try an implicit conversion instead? This works better with Java APIs that like to create their own objects. So you would
class SafeIssue(issue: Issue) {
def original = issue
def safeFoo = Option(issue.foo)
// ... You must write any of these you need
}
implicit def make_issues_safe(issue: Issue) = new SafeIssue(issue)
Then you can--as long as you've supplied the method--write things like
val yay = Issue.myStaticFactoryMethodThing.safeFoo.map(x => pleaseNoNull(x))
(You can then decide whether you want to carry SafeIssue or Issue around in your code, and you can always get back the Issue from SafeIssue with the exposed original method (or you could make the issue parameter a val.)
data: [
{
type: "earnings"
info: {
earnings: 45.6
dividends: 4052.94
gains: 0
expenses: 3935.24
shares_bought: 0
shares_bought_user_count: 0
shares_sold: 0
shares_sold_user_count: 0
}
created: "2011-07-04 11:46:17"
}
{
type: "mentions"
info: [
{
type_id: "twitter"
mentioner_ticker: "LOANS"
mentioner_full_name: "ERICK STROBEL"
}
]
created: "2011-06-10 23:03:02"
}
]
Here's my problem : like you can see the "info" is different in each of one, one is a json object, and one is a json array, i usually choose Gson to take the data, but with Gson we can't do this kind of thing . How can i make it work ?
If you want to use Gson, then to handle the issue where the same JSON element value is sometimes an array and sometimes an object, custom deserialization processing is necessary. I posted an example of this in the Parsing JSON with GSON, object sometimes contains list sometimes contains object post.
If the "info" element object has different elements based on type, and so you want polymorphic deserialization behavior to deserialize to the correct type of object, with Gson you'll also need to implement custom deserialization processing. How to do that has been covered in other StackOverflow.com posts. I posted a link to four different such questions and answers (some with code examples) in the Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied thread. In this thread, the particular structure of the JSON objects to deserialize varies from the examples I just linked, because the element to indicate the type is external of the object to be deserialized, but if you can understand the other examples, then handling the problem here should be easy.
Both key and value have to be within quotes, and you need to separate definitions with commas:
{
"key0": "value0",
"key1": "value1",
"key2": [ "value2_0", "value2_1" ]
}
That should do the trick!
The info object should be of the same type with every type.
So check the type first. Pseudocode:
if (data.get('type').equals("mentions") {
json_arr = data.get('info');
}
else if (data.get('type').equals("earnings") {
json_obj = data.get('info');
}
I'm not sure that helps, cause I'm not sure I understand the question.
Use simply org.json classes that are available in android: http://developer.android.com/reference/org/json/package-summary.html
You will get a dynamic structure that you will be able to traverse, without the limitations of strong typing.....
This is not a "usual" way of doing things in Java (where strong typing is default) but IMHO in many situations even in Java it is ok to do some dynamic processing. Flexibility is better but price to pay is lack of compile-time type verification... Which in many cases is ok.
If changing libraries is an option you could have a look at Jackson, its Simple Data Binding mode should allow you to deserialize an object like you describe about. A part of the doc that is probably quite important is this, your example would already need JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES to work...
Clarification for Bruce: true, in Jackson's Full Data Binding mode, but not in Simple Data Binding mode. This is simple data binding:
public static void main(String[] args) throws IOException {
File src = new File("test.json");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature. ALLOW_UNQUOTED_FIELD_NAMES, true);
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS,true);
Object root = mapper.readValue(src, Object.class);
Map<?,?> rootAsMap = mapper.readValue(src, Map.class);
System.out.println(rootAsMap);
}
which with OP's sightly corrected sample JSON data gives:
{data=[{type=earnings, info={earnings=45.6, dividends=4052.94, gains=0,
expenses=3935.24, shares_bought=0, shares_bought_user_count=0, shares_sold=0,
shares_sold_user_count=0}, created=2011-07-04 11:46:17}, {type=mentions,
info=[{type_id=twitter, mentioner_ticker=LOANS, mentioner_full_name=ERICK STROBEL}],
created=2011-06-10 23:03:02}]}
OK, some hand-coding needed to wire up this Map to the original data, but quite often less is more and such mapping code, being dead simple has the advantage of being very easy to read/maintain later on.