Last active
June 17, 2016 09:10
-
-
Save benjaminaaron/acb5a92d43667e20b54bf2ef7a733cb7 to your computer and use it in GitHub Desktop.
Jackson: strict parsing of json-string into Map<ModelType, Attributes>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class Attributes {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AttributesExample1 extends Attributes { | |
private String str = "foo"; | |
private double dbl = 0.8; | |
private boolean bool = false; | |
private AttributesExample2 attributesExample2 = new AttributesExample2(); | |
public String toString() { | |
return str + ", " + dbl + ", " + bool + ", attributesExample2: " + attributesExample2; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AttributesExample2 extends Attributes { | |
private int inti = 5; | |
private boolean booli = false; | |
public String toString() { | |
return inti + ", " + booli; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.fasterxml.jackson.annotation.JsonAutoDetect; | |
import com.fasterxml.jackson.annotation.PropertyAccessor; | |
import com.fasterxml.jackson.core.JsonParseException; | |
import com.fasterxml.jackson.core.JsonParser; | |
import com.fasterxml.jackson.databind.*; | |
import com.fasterxml.jackson.databind.module.SimpleModule; | |
import java.io.IOException; | |
import java.util.*; | |
public class Main { | |
public static void main(String[] args) throws IOException { | |
ObjectMapper mapper = new ObjectMapper(); | |
mapper.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false); // otherwise 4.7 will automatically be casted to 4 for integers, with this it throws an error | |
mapper.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION); // forbids duplicate keys | |
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); // otherwise private fields won't be usable | |
mapper.registerModule(new SimpleModule().addDeserializer(boolean.class, new JsonDeserializer<Boolean>() { // make boolean parsing more strict, otherwise integers are accepted with 0=false and all other integers=true | |
@Override | |
public Boolean deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { | |
if (!jsonParser.getCurrentToken().isBoolean()) | |
throw new JsonParseException(jsonParser, "Can't parse \"" + jsonParser.getValueAsString() + "\" as boolean"); | |
return jsonParser.getValueAsBoolean(); | |
} | |
})); | |
String json = "{" + | |
"\"MODEL1\": {" + | |
"\"str\": \"hi\", " + | |
"\"dbl\": 2.0, " + | |
"\"bool\": true, " + | |
"\"attributesExample2\": {" + | |
"\"inti\": 4, " + | |
"\"booli\": true" + | |
"}}," + | |
"\"MODEL2\": {" + | |
"\"inti\": 2, " + | |
"\"booli\": false" + | |
"}}"; | |
Map<ModelType, Attributes> modelsMap = new HashMap<>(); | |
Iterator<Map.Entry<String, JsonNode>> nodeIterator = mapper.readTree(json).fields(); // via stackoverflow.com/a/18342245 | |
while (nodeIterator.hasNext()) { | |
Map.Entry<String, JsonNode> entry = nodeIterator.next(); | |
ModelType modelType = ModelType.valueOf(entry.getKey()); | |
Attributes attributes = (Attributes) mapper.treeToValue(entry.getValue(), modelType.getAttributesClass()); // via stackoverflow.com/a/28714523 | |
modelsMap.put(modelType, attributes); | |
} | |
System.out.println(modelsMap); // prints --> {MODEL2=2, false, MODEL1=hi, 2.0, true, attributesExample2: 4, true} | |
// TODO syntactic checks are done, now check modelsMap for logical soundness (order & valid mix?) before passing it to the simulator... | |
//usage example: | |
AttributesExample1 ae1 = (AttributesExample1) modelsMap.get(ModelType.MODEL1); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum ModelType { | |
MODEL1(AttributesExample1.class), | |
MODEL2(AttributesExample2.class); | |
private Class<? extends Attributes> attributes; | |
private ModelType(Class<? extends Attributes> attributesClass) { | |
attributes = attributesClass; | |
} | |
public Class<? extends Attributes> getAttributesClass() { | |
return attributes; | |
} | |
} |
Danke, sieht besser aus, hab's übernommen 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ModelType Klasse würd ich anders machen. Bei dieser Version ist das Problem, dass man ein Model hinzufügen kann, aber es im static initializer vergessen könnte.
Man sollte das besser so machen:
Außerdem für mehr Typsicherheit und um Warnungen keine Compiler-Warnungen zu haben, Class parametrisieren. Entweder Class<?> oder Class<? extends Attributes>. Aber ohne <> gibt's glaub ich eine "raw type warning" oder so.