Any function similar to jackson's objectMapper.readValue?
Closed this issue · 6 comments
When using jackson, one can use
JsonFactory jsonFactory = new JsonFactory();
ObjectMapper objectMapper = new ObjectMapper(jsonFactory);
objectMapper.readValue(jsonString, TYPE);
to transfer json to Object or using writeValueAsString
vice versa.
I'd like to know is there any function in simdjson can do the same thing?
Currently, there is no such function. However, there are plans to add it.
Thx. Looking forward to this feature.
Additionally, I saw toString()
in JsonValue.java:
@Override
public String toString() {
switch (tape.getType(tapeIdx)) {
case INT64 -> {
return String.valueOf(asLong());
}
case DOUBLE -> {
return String.valueOf(asDouble());
}
case TRUE_VALUE, FALSE_VALUE -> {
return String.valueOf(asBoolean());
}
case STRING -> {
return asString();
}
case NULL_VALUE -> {
return "null";
}
case START_OBJECT -> {
return "<object>";
}
case START_ARRAY -> {
return "<array>";
}
default -> {
return "unknown";
}
}
}
IMHO START_OBJECT is the part I mentioned before. But how about array? If we have elements in json which type is array, we cannot use get
to get the value of the array?
Do you mean something like this:
JsonValue json = parser.parse(...);
JsonValue[] array = json.getArray();
?
If that's the case, then currently it's not available. The only option is to use JsonValue::arrayIterator
.
for toString
currently I'm using this workaround
void stringify(JsonValue v, StringBuilder w) {
if (v.isArray()) {
w.append('[');
final var iter = v.arrayIterator();
while (iter.hasNext()) {
final var element = iter.next();
stringify(element, w);
}
w.append('[');
} else if (v.isObject()) {
w.append('{');
final var iter = v.objectIterator();
boolean first = true;
while (iter.hasNext()) {
if (!first) w.append(',');
final var element = iter.next();
w.append('\"');
w.append(element.getKey());
w.append('\"');
w.append(':');
stringify(element.getValue(), w);
first = false;
}
w.append('}');
} else if (v.isString()) {
w.append('\"');
// may try to find vectorized version
w.append(com.fasterxml.jackson.core.util.BufferRecyclers.getJsonStringEncoder().quoteAsString(v.asString()));
w.append('\"');
} else {
w.append(v);
}
}
so you can use it like
JsonValue jsonNode = entry.getValue();
if (jsonNode != null && !jsonNode.isNull()) {
final var sb = new StringBuilder();
stringify(jsonNode, sb);
// ... use sb
}
but this is slow. I wonder if there is a way to use stringBuffer
or buffer
of the JsonNode
instead to achieve the same effect?
I'm using the similar workaround as you by modifying toString() @andyglow
@Override
public String toString() {
switch (tape.getType(tapeIdx)) {
case INT64 -> {
return String.valueOf(asLong());
}
case DOUBLE -> {
return String.valueOf(asDouble());
}
case TRUE_VALUE, FALSE_VALUE -> {
return String.valueOf(asBoolean());
}
case STRING -> {
return asString();
}
case NULL_VALUE -> {
return "null";
}
case START_OBJECT -> {
Iterator<Map.Entry<String, JsonValue>> it = this.objectIterator();
String result = "{";
boolean first = true;
while (it.hasNext()) {
if(!first)
result += ", ";
Map.Entry<String, JsonValue> field = it.next();
result += field.getKey() + "=" + field.getValue().toString();
first = false;
}
result += "}";
return result;
}
case START_ARRAY -> {
Iterator<JsonValue> it = this.arrayIterator();
String result = "[";
boolean first = true;
while (it.hasNext()) {
if(!first)
result += ", ";
JsonValue field = it.next();
result += field.toString();
first = false;
}
result += "]";
return result;
}
default -> {
return "unknown";
}
}
}
I think you have a little typo mistake, line 9 of stringify() should be w.append(']');