mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Extract JsonWriter for json output
This commit is contained in:
parent
d4b4bd8603
commit
03bf043959
6 changed files with 94 additions and 89 deletions
|
@ -1,45 +1,42 @@
|
|||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import org.asamk.signal.json.JsonError;
|
||||
import org.asamk.signal.json.JsonMessageEnvelope;
|
||||
import org.asamk.signal.manager.Manager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler {
|
||||
|
||||
final Manager m;
|
||||
private final ObjectMapper jsonProcessor;
|
||||
private final static Logger logger = LoggerFactory.getLogger(JsonReceiveMessageHandler.class);
|
||||
|
||||
protected final Manager m;
|
||||
private final JsonWriter jsonWriter;
|
||||
|
||||
public JsonReceiveMessageHandler(Manager m) {
|
||||
this.m = m;
|
||||
this.jsonProcessor = new ObjectMapper();
|
||||
jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
jsonWriter = new JsonWriter(System.out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
|
||||
ObjectNode result = jsonProcessor.createObjectNode();
|
||||
final Map<String, Object> object = new HashMap<>();
|
||||
if (exception != null) {
|
||||
result.putPOJO("error", new JsonError(exception));
|
||||
object.put("error", new JsonError(exception));
|
||||
}
|
||||
if (envelope != null) {
|
||||
result.putPOJO("envelope", new JsonMessageEnvelope(envelope, content, m));
|
||||
object.put("envelope", new JsonMessageEnvelope(envelope, content, m));
|
||||
}
|
||||
try {
|
||||
jsonProcessor.writeValue(System.out, result);
|
||||
System.out.println();
|
||||
jsonWriter.write(object);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Failed to write json object: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
37
src/main/java/org/asamk/signal/JsonWriter.java
Normal file
37
src/main/java/org/asamk/signal/JsonWriter.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class JsonWriter {
|
||||
|
||||
private final OutputStreamWriter writer;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public JsonWriter(final OutputStream writer) {
|
||||
this.writer = new OutputStreamWriter(writer, StandardCharsets.UTF_8);
|
||||
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
objectMapper.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
}
|
||||
|
||||
public void write(final Object object) throws IOException {
|
||||
try {
|
||||
objectMapper.writeValue(writer, object);
|
||||
} catch (JsonProcessingException e) {
|
||||
// Some issue with json serialization, probably caused by a bug
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
writer.write(System.lineSeparator());
|
||||
writer.flush();
|
||||
}
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
package org.asamk.signal.commands;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import net.sourceforge.argparse4j.impl.Arguments;
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
import net.sourceforge.argparse4j.inf.Subparser;
|
||||
|
||||
import org.asamk.signal.JsonWriter;
|
||||
import org.asamk.signal.OutputType;
|
||||
import org.asamk.signal.manager.Manager;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -20,7 +18,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class GetUserStatusCommand implements LocalCommand {
|
||||
|
||||
// TODO delete later when "json" variable is removed
|
||||
private final static Logger logger = LoggerFactory.getLogger(GetUserStatusCommand.class);
|
||||
|
||||
@Override
|
||||
|
@ -35,9 +32,6 @@ public class GetUserStatusCommand implements LocalCommand {
|
|||
@Override
|
||||
public int handleCommand(final Namespace ns, final Manager m) {
|
||||
// Setup the json object mapper
|
||||
ObjectMapper jsonProcessor = new ObjectMapper();
|
||||
jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
|
||||
boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
|
||||
|
||||
// TODO delete later when "json" variable is removed
|
||||
|
@ -56,16 +50,18 @@ public class GetUserStatusCommand implements LocalCommand {
|
|||
|
||||
// Output
|
||||
if (inJson) {
|
||||
List<JsonIsRegistered> objects = registered.entrySet()
|
||||
final JsonWriter jsonWriter = new JsonWriter(System.out);
|
||||
|
||||
List<JsonUserStatus> jsonUserStatuses = registered.entrySet()
|
||||
.stream()
|
||||
.map(entry -> new JsonIsRegistered(entry.getKey(), entry.getValue()))
|
||||
.map(entry -> new JsonUserStatus(entry.getKey(), entry.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
try {
|
||||
jsonProcessor.writeValue(System.out, objects);
|
||||
System.out.println();
|
||||
jsonWriter.write(jsonUserStatuses);
|
||||
} catch (IOException e) {
|
||||
System.err.println(e.getMessage());
|
||||
logger.error("Failed to write json object: {}", e.getMessage());
|
||||
return 3;
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<String, Boolean> entry : registered.entrySet()) {
|
||||
|
@ -76,13 +72,13 @@ public class GetUserStatusCommand implements LocalCommand {
|
|||
return 0;
|
||||
}
|
||||
|
||||
private static final class JsonIsRegistered {
|
||||
private static final class JsonUserStatus {
|
||||
|
||||
public String name;
|
||||
|
||||
public boolean isRegistered;
|
||||
|
||||
public JsonIsRegistered(String name, boolean isRegistered) {
|
||||
public JsonUserStatus(String name, boolean isRegistered) {
|
||||
this.name = name;
|
||||
this.isRegistered = isRegistered;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
package org.asamk.signal.commands;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import net.sourceforge.argparse4j.impl.Arguments;
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
import net.sourceforge.argparse4j.inf.Subparser;
|
||||
|
||||
import org.asamk.signal.JsonWriter;
|
||||
import org.asamk.signal.OutputType;
|
||||
import org.asamk.signal.manager.Manager;
|
||||
import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
|
||||
import org.asamk.signal.manager.storage.groups.GroupInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -23,6 +21,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class ListGroupsCommand implements LocalCommand {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ListGroupsCommand.class);
|
||||
|
||||
private static Set<String> resolveMembers(Manager m, Set<SignalServiceAddress> addresses) {
|
||||
return addresses.stream()
|
||||
.map(m::resolveSignalServiceAddress)
|
||||
|
@ -30,18 +30,6 @@ public class ListGroupsCommand implements LocalCommand {
|
|||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private static int printGroupsJson(ObjectMapper jsonProcessor, List<?> objects) {
|
||||
try {
|
||||
jsonProcessor.writeValue(System.out, objects);
|
||||
System.out.println();
|
||||
} catch (IOException e) {
|
||||
System.err.println(e.getMessage());
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void printGroupPlainText(Manager m, GroupInfo group, boolean detailed) {
|
||||
if (detailed) {
|
||||
final GroupInviteLinkUrl groupInviteLink = group.getGroupInviteLink();
|
||||
|
@ -77,15 +65,13 @@ public class ListGroupsCommand implements LocalCommand {
|
|||
@Override
|
||||
public int handleCommand(final Namespace ns, final Manager m) {
|
||||
if (ns.get("output") == OutputType.JSON) {
|
||||
final ObjectMapper jsonProcessor = new ObjectMapper();
|
||||
jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
final JsonWriter jsonWriter = new JsonWriter(System.out);
|
||||
|
||||
List<JsonGroup> objects = new ArrayList<>();
|
||||
List<JsonGroup> jsonGroups = new ArrayList<>();
|
||||
for (GroupInfo group : m.getGroups()) {
|
||||
final GroupInviteLinkUrl groupInviteLink = group.getGroupInviteLink();
|
||||
|
||||
objects.add(new JsonGroup(group.getGroupId().toBase64(),
|
||||
jsonGroups.add(new JsonGroup(group.getGroupId().toBase64(),
|
||||
group.getTitle(),
|
||||
group.isMember(m.getSelfAddress()),
|
||||
group.isBlocked(),
|
||||
|
@ -94,7 +80,15 @@ public class ListGroupsCommand implements LocalCommand {
|
|||
resolveMembers(m, group.getRequestingMembers()),
|
||||
groupInviteLink == null ? null : groupInviteLink.getUrl()));
|
||||
}
|
||||
return printGroupsJson(jsonProcessor, objects);
|
||||
|
||||
try {
|
||||
jsonWriter.write(jsonGroups);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to write json object: {}", e.getMessage());
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
boolean detailed = ns.getBoolean("detailed");
|
||||
for (GroupInfo group : m.getGroups()) {
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
package org.asamk.signal.commands;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import net.sourceforge.argparse4j.impl.Arguments;
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
import net.sourceforge.argparse4j.inf.Subparser;
|
||||
|
||||
import org.asamk.Signal;
|
||||
import org.asamk.signal.JsonReceiveMessageHandler;
|
||||
import org.asamk.signal.JsonWriter;
|
||||
import org.asamk.signal.OutputType;
|
||||
import org.asamk.signal.ReceiveMessageHandler;
|
||||
import org.asamk.signal.json.JsonMessageEnvelope;
|
||||
|
@ -24,13 +19,13 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
|
||||
|
||||
public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
||||
|
||||
// TODO delete later when "json" variable is removed
|
||||
private final static Logger logger = LoggerFactory.getLogger(ReceiveCommand.class);
|
||||
|
||||
@Override
|
||||
|
@ -47,8 +42,6 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
|||
}
|
||||
|
||||
public int handleCommand(final Namespace ns, final Signal signal, DBusConnection dbusconnection) {
|
||||
final ObjectMapper jsonProcessor;
|
||||
|
||||
boolean inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
|
||||
|
||||
// TODO delete later when "json" variable is removed
|
||||
|
@ -56,24 +49,16 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
|||
logger.warn("\"--json\" option has been deprecated, please use the global \"--output=json\" instead.");
|
||||
}
|
||||
|
||||
if (inJson) {
|
||||
jsonProcessor = new ObjectMapper();
|
||||
jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
} else {
|
||||
jsonProcessor = null;
|
||||
}
|
||||
final JsonWriter jsonWriter = inJson ? new JsonWriter(System.out) : null;
|
||||
try {
|
||||
dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> {
|
||||
if (jsonProcessor != null) {
|
||||
if (jsonWriter != null) {
|
||||
JsonMessageEnvelope envelope = new JsonMessageEnvelope(messageReceived);
|
||||
ObjectNode result = jsonProcessor.createObjectNode();
|
||||
result.putPOJO("envelope", envelope);
|
||||
final Map<String, JsonMessageEnvelope> object = Map.of("envelope", envelope);
|
||||
try {
|
||||
jsonProcessor.writeValue(System.out, result);
|
||||
System.out.println();
|
||||
jsonWriter.write(object);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Failed to write json object: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.out.print(String.format("Envelope from: %s\nTimestamp: %s\nBody: %s\n",
|
||||
|
@ -95,15 +80,13 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
|||
});
|
||||
|
||||
dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> {
|
||||
if (jsonProcessor != null) {
|
||||
if (jsonWriter != null) {
|
||||
JsonMessageEnvelope envelope = new JsonMessageEnvelope(receiptReceived);
|
||||
ObjectNode result = jsonProcessor.createObjectNode();
|
||||
result.putPOJO("envelope", envelope);
|
||||
final Map<String, JsonMessageEnvelope> object = Map.of("envelope", envelope);
|
||||
try {
|
||||
jsonProcessor.writeValue(System.out, result);
|
||||
System.out.println();
|
||||
jsonWriter.write(object);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Failed to write json object: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.out.print(String.format("Receipt from: %s\nTimestamp: %s\n",
|
||||
|
@ -113,15 +96,13 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
|||
});
|
||||
|
||||
dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> {
|
||||
if (jsonProcessor != null) {
|
||||
if (jsonWriter != null) {
|
||||
JsonMessageEnvelope envelope = new JsonMessageEnvelope(syncReceived);
|
||||
ObjectNode result = jsonProcessor.createObjectNode();
|
||||
result.putPOJO("envelope", envelope);
|
||||
final Map<String, JsonMessageEnvelope> object = Map.of("envelope", envelope);
|
||||
try {
|
||||
jsonProcessor.writeValue(System.out, result);
|
||||
System.out.println();
|
||||
jsonWriter.write(object);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Failed to write json object: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.out.print(String.format("Sync Envelope from: %s to: %s\nTimestamp: %s\nBody: %s\n",
|
||||
|
|
|
@ -91,7 +91,7 @@ public class SignalAccount implements Closeable {
|
|||
this.fileChannel = fileChannel;
|
||||
this.lock = lock;
|
||||
jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); // disable autodetect
|
||||
jsonProcessor.enable(SerializationFeature.INDENT_OUTPUT); // for pretty print, you can disable it.
|
||||
jsonProcessor.enable(SerializationFeature.INDENT_OUTPUT); // for pretty print
|
||||
jsonProcessor.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
jsonProcessor.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
|
||||
jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue