Yago Rodriguez Yago Rodriguez - 4 months ago 10
JSON Question

How to declare a variable type knowing its type by a string

I'm trying to declare a variable type using a json document...
The problem is that i need to declare its type Long or Double and that depends on the string for example:

the raw value is a double:

{"raw":119970000,"fmt":"119.97M","longFmt":"119,970,000"}


this is a Double too:

{"raw":0.068,"fmt":"6.80%"}


but this is a long:

{"raw":1443571200,"fmt":"2015-09-30"}


i'm using regex on the "fmt" fields so i can know the type but the proble i got is at the moment of declaring the type

i'm trying to do this but there is an error and i don't know exactly why.

This is my "Field" Class:

public class Field {

@JsonProperty("raw") private RawField raw;
@JsonProperty("fmt") private String fmt;
@JsonIgnore private FieldType fieldType;

@JsonCreator
public Field(
@JsonProperty("raw") RawField raw,
@JsonProperty("fmt") final String fmt
) {
this.setFmt(fmt);
this.setRaw(raw, fmt);
}

private boolean isDate(String fmt){
Pattern datePattern = Pattern.compile(
"[0-9]{4}-(([1][0-2])|(0[0-9]))-((0[1-9])|(1[0-9])|(2[0-9])|(3[0-1]))"
);
Matcher matcher = datePattern.matcher(fmt);
return matcher.find();
}

private boolean isDouble(String fmt) {
Pattern datePattern = Pattern.compile(
"[0-9]+\\.?[0-9]*(M|B|%)?$"
);
Matcher matcher = datePattern.matcher(fmt);
return !isDate(fmt) && matcher.find();
}


public String getFmt() {
return fmt;
}

public void setFmt(final String fmt) {
this.fmt = fmt;
}

public RawField getRaw() {
return raw;
}

public void setRaw(final RawField raw) {
this.raw = raw;
}

private void setRaw(final RawField raw, String fmt) {
if(isDate(fmt)) {
this.raw = new RawField<Long>(raw); //error
} else {
if(isDouble(fmt)){
this.raw = new RawField<Double>(raw); //error
}
}


}
}


and this is my RawField class:

public class RawField <E> {

@JsonProperty("raw") private E rawField;

@JsonCreator
public RawField (E rawField){
this.setRawField(rawField);
}

@JsonProperty("raw")
public void setRawField(E rawField) {
this.rawField = rawField;
}
@JsonProperty("raw")
public E getRawField() {
return rawField;
}
}

Answer

The generic class RawField<E extends Number> for E being either Long or Double is cumbersome, because of type erasure.

So I would use either the base type, Number, or a one-in-all BigDecimal

 Number raw;

 private void setRaw(final RawField raw, String fmt) {
    if(isDate(fmt)) {
      long t = ...
      this.raw = t;
    } else {
      if(isDouble(fmt)) {
        double x = .... 
        this.raw = x;
      }
    }
  }

  double y = field.raw.doubleValue();
  long n = field.raw.longValue();
  if (field.raw instanceof Double) { ... }

BigDecimal would have the advantage over a double by having a precision: new BigDecimal("3.14") has a precision of 2 and is exact.