I am trying to get familar with Messagepack for Java.
I get the data via Mqtt. If the variable is not null everything is fine but the variable can also be null and in this case I will get this Exception: Expected Int, but got Nil (c0)
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(m.getPayload());
int someInt = unpacker.unpackInt();
String someString = unpacker.unpackString();
So far I was not able to figure out how to get NULL back
I want to avoid to use TRY/CATCH so currently I am using this way
int someInt = unpacker.getNextFormat().equals("NIL") ? unpacker.unpackInt() : null;
Is there a better way ?
I looked the javadoc of MessageUnpacker and it doesn't seem provide a better way.
The example code is very close of your way :
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
while(unpacker.hasNext()) {
MessageFormat f = unpacker.getNextFormat();
switch(f) {
case MessageFormat.POSFIXINT:
case MessageFormat.INT8:
case MessageFormat.UINT8: {
int v = unpacker.unpackInt();
break;
}
case MessageFormat.STRING: {
String v = unpacker.unpackString();
break;
}
// ...
}
}
So I think that you are in the good path.
But if you repeat this retrieval multiple times(and it is very likely), you could introduce utility methods that does the job for you.
For example for unpackInt() :
public Integer unpackIntOrNull (MessageUnpacker unpacker){
return unpacker.getNextFormat() == MessageFormat.INT8 ?
unpacker.unpackInt() : null;
}
And now, it is very straight to unpack elements :
Integer einInt = unpackIntOrNull(unpacker);
Integer einAndereInt = unpackIntOrNull(unpacker);
...
MessageUnpacker has a method named tryUnpackNil. If the next byte is a nil value, this method reads it and returns true, otherwise reads nothing and returns false.
This can be used to skip over nil values, and unpack non-nil values with e.g.:
final MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(data);
final Integer value = unpacker.tryUnpackNil() ? null : unpacker.unpackInt();
Related
somebody explain me how can handle null values in google protobuf .
i have structure like this :
syntax = "proto3";
import "google/protobuf/wrappers.proto";
message Person {
google.protobuf.DoubleValue age = 4;
}
and java code :
DoubleValue myAge = null;
Person build = Person.newBuilder()
.setAge(myAge) // <- NPE
.build();
this code result null pointer exception on .setAge(myAge) line.
so what is use case of protobuf DoubleValue ? I thought it was used to manage null values . but still receive NullPointerException .
Do you use code like this for handle this problem ?
DoubleValue a = null;
Person.Builder builder = Person.newBuilder();
if (a != null) {
builder.setAge(a);
}
Person build = builder.build();
UPDATE:
this is part of code generated by protoc command :
/**
* <code>.google.protobuf.DoubleValue age = 9;</code>
*/
public Builder setAge(com.google.protobuf.DoubleValue value) {
if (ageBuilder_ == null) {
if (value == null) { //<-- Additional statement
throw new NullPointerException();
}
age_ = value;
onChanged();
} else {
ageBuilder_.setMessage(value);
}
Why set additional if statement in generated code ?
I think this is a bug for google protocol buffer.
finally i wrote this code:
DoubleValue.Builder builder = DoubleValue.newBuilder();
DoubleValue myAge = null;
Person build = Person.newBuilder()
.setAge(myAge != null ? myAge : builder )
.build();
DoubleValue is meant to handle missing values, not necessarily null. Protobuf libraries are intended to never involve nulls - for example, it never returns null, even for missing fields. Also, as you've found out, setters don't accept null. For example, to clear a field you'd use clearField instead of setField(null).
One of the big differences between proto2 and proto3 is that (initially) "hazzers" for primitive fields (e.g. hasField) were removed. That is, if you have a double my_field, there is no way to tell if it was never set, or set explicitly to zero. getMyField() would return 0 in both cases.
Note that messages still have hazzers, so if you want that functionality, you could wrap your primitive field in a message. Which is exactly what DoubleValue is. So if you have a field DoubleValue age = 1, you could use hasAge() to determine if it's set. In newer protobuf version, you could do the same with optional double age = 1.
Note that all of this has no relation with null in the Java generated code. There really is no way a setter would accept a null value.
TL;DR: Your first suggestion is good and very common:
DoubleValue a = null;
Person.Builder builder = Person.newBuilder();
if (a != null) {
builder.setAge(a);
}
Person build = builder.build();
If instead of null you have an Optional, you could use a similar variant:
OptionalDouble a = OptionalDouble.empty();
Person.Builder builder = Person.newBuilder();
a.ifPresent(value-> builder.getAgeBuilder().setValue(value));
Person build = builder.build();
I'm trying to use the following piece of code posted on goo.gl/av3tJD
val supportsDistortionCorrection = characteristics.get(
CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES)?.contains(
CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY) ?: false
I see the code is in Kotlin, which I know very little about.
I want to convert the code to Java.
I'm trying the following:
Boolean hasNoiseReduction = false;
//cc is my previously defined CameraCharacteristics object
if(cc.get(CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES).contains("some string"))hasNoiseReduction = true;
The method contains is throwing me off. I don't believe is the method contains used in the String class.
Any advice is needed
it.first at that point in the code is referring to the first element of the Pair created above, containing a CameraCharacteristics instance. The get on this returns an IntArray (int[] in Java terms), and the contains method from the Kotlin standard library checks whether the given constant is in that array.
val cameraCharacteristics: CameraCharacteristics = it.first
val capabilities: IntArray = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)!!
capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)
You could check this in Java by - for example - looping through the array elements and seeing if you find the value. A primitive implementation for this:
CameraCharacteristics cameraCharacteristics = ...;
final int[] capabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
boolean contains = false;
for (final int capability : capabilities) {
if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
contains = true;
break;
}
}
// use result
How can i rewrite this:
private Comparator<Domain> byRank;
...
byRank = new Comparator<Domain>() {
#Override
public int compare(Domain d1, Domain d2) {
float tmp1 = d1.getDomainRank() == null ? 0 : d1.getDomainRank();
float tmp2 = d2.getDomainRank() == null ? 0 : d2.getDomainRank();
return Float.compare(tmp1, tmp2);
}
};
into lambda?
According to check null value before sorting using lambda expression, I tried this:
byRank = Comparator.nullsFirst(Comparator.comparing(Domain::getDomainRank));
However, it fails with:
java.lang.NullPointerException: null
at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
at java.util.Comparators$NullComparator.compare(Comparators.java:83)
at java.util.PriorityQueue.siftUpUsingComparator(PriorityQueue.java:669)
at java.util.PriorityQueue.siftUp(PriorityQueue.java:645)
at java.util.PriorityQueue.offer(PriorityQueue.java:344)
at java.util.PriorityQueue.add(PriorityQueue.java:321)
Edit: the lambda fails even if I check compared objects for null before comparison:
Queue<Domain> topByRank = new PriorityQueue<>(TOP, byRank);
...
for (Domain domain : domains) {
if (domain == null) { // check here
continue;
}
topByRank.add(domain); // here it fails
}
It should be:
Comparator.comparing(Domain::getDomainRank,
Comparator.nullsFirst(Comparator.naturalOrder()))
So we sort a list based on domainRank. But what are we going to do with Domain objects whose domainRank value is null? We going to keep them at the head of our collection:
Comparator.nullsFirst(Comparator.naturalOrder())
Your code will put null Domains first. If you want to check for null rank, you need to use this:
Comparator.comparing(Domain::getDomainRank, Comparator.nullsFirst(Comparator.naturalOrder()))
But keep in mind that this is only equivalent to your original comparator if the rank can't be less than 0. Otherwise, you'll have to test a similar expression:
Comparator.comparing(d -> d.getDomainRank() == null ? 0 : d.getDomainRank())
Alternatively, you might have meant to use Float.MIN_VALUE instead of 0 in your original code.
I am getting a JSONObject from a webservice call.
JSONObject result = ...........
When i am accessing like result.getString("fieldName");
If the fieldName exist in that JSONObject then it is working fine.If that is not exist i am getting exception JSONObject["fieldName"] not found.
I can use try catch for this.But i have nearly 20 fields like this.Am i need to use 20 try catch blocks for this or is there any alternative for this.Thanks in advance...
There is a method JSONObject#has(key) meant for exactly this purpose. This way you can avoid the exception handling for each field.
if(result.has("fieldName")) {
// It exists, do your stuff
} else {
// It doesn't exist, do nothing
}
Also, you can use the JSONObject#isNull(str) method to check if it is null or not.
if(result.isNull("fieldName")) {
// It doesn't exist, do nothing
} else {
// It exists, do your stuff
}
You can also move the logic to a common method (for code reusability), where you can pass any JSONObject & the field name and the method will return if the field is present or not.
Assuming that you're using org.json.JSONObject, you can use JSONObject#optString(String key, String defaultValue) instead. It will return defaultValue, if key is absent:
String value = obj.optString(fieldName, defaultValueIfNull);
Way better solution is to use optString instead of getString.
String name = jsonObject.optString("fieldName");
// it will return an empty string ("") if the key you specify doesn't exist
Check if your JsonObject implementation contains method called "has". It could be checks if property exist in object.
Many JsonObject implementations contains this method.
I use this code to do so, it returns undefined or a specified defaultValue instead of rising exception
/* ex: getProperty(myObj,'aze.xyz',0) // return myObj.aze.xyz safely
* accepts array for property names:
* getProperty(myObj,['aze','xyz'],{value: null})
*/
function getProperty(obj, props, defaultValue) {
var res, isvoid = function(x){return typeof x === "undefined" || x === null;}
if(!isvoid(obj)){
if(isvoid(props)) props = [];
if(typeof props === "string") props = props.trim().split(".");
if(props.constructor === Array){
res = props.length>1 ? getProperty(obj[props.shift()],props,defaultValue) : obj[props[0]];
}
}
return typeof res === "undefined" ? defaultValue: res;
}
I'm looking for a Google Collections method that returns the first result of a sequence of Suppliers that doesn't return null.
I was looking at using Iterables.find() but in my Predicate I would have to call my supplier to compare the result against null, and then have to call it again once the find method returned the supplier.
Given your comment to Calm Storm's answer (the desire not to call Supplier.get() twice), then what about:
private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
public X apply(Supplier<X> in) {
// If you will never have a null Supplier, you can skip the test;
// otherwise, null Supplier will be treated same as one that returns null
// from get(), i.e. skipped
return (in == null) ? null : in.get();
}
}
then
Iterable<Supplier<X>> suppliers = ... wherever this comes from ...
Iterable<X> supplied = Iterables.transform(suppliers, SUPPLY);
X first = Iterables.find(supplied, Predicates.notNull());
note that the Iterable that comes out of Iterables.transform() is lazily-evaluated, therefore as Iterables.find() loops over it, you only evaluate as far as the first non-null-returning one, and that only once.
You asked for how to do this using Google Collections, but here's how you would do it without using Google Collections. Compare it to Cowan's answer (which is a good answer) -- which is easier to understand?
private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
for (Supplier<Thing> supplier : thingSuppliers) {
Thing thing = supplier.get();
if (thing != null) {
return thing;
}
}
// throw exception or return null
}
In place of the comment -- if this was the fault of the caller of your class, throw IllegalArgumentException or IllegalStateException as appropriate; if this shouldn't have ever happened, use AssertionError; if it's a normal occurrence your code that invokes this expects to have to check for, you might return null.
What is wrong with this?
List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
boolean apply(Supplier supplier) {
return supplier.isSomeMethodCall() == null;
}
boolean equals(Object o) {
return false;
}
});
Are you trying to save some lines? The only optimisation I can think is to static import the find so you can get rid of "Iterables". Also the predicate is an anonymous inner class, if you need it in more than one place you can create a class and it would look as,
List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
Where SupplierPredicateFinder is another class.
UPDATE : In that case find is the wrong method. You actually need a custom function like this which can return two values. If you are using commons-collections then you can use a DefaultMapEntry or you can simply return an Object[2] or a Map.Entry.
public static DefaultMapEntry getSupplier(List<Supplier> list) {
for(Supplier s : list) {
Object heavyObject = s.invokeCostlyMethod();
if(heavyObject != null) {
return new DefaultMapEntry(s, heavyObject);
}
}
}
Replace the DefaultMapEntry with a List of size 2 or a hashmap of size 1 or an array of length 2 :)