diff --git a/logstash-core/src/main/java/org/logstash/ext/JrubyTimestampExtLibrary.java b/logstash-core/src/main/java/org/logstash/ext/JrubyTimestampExtLibrary.java index 58a58eaad..50e3532db 100644 --- a/logstash-core/src/main/java/org/logstash/ext/JrubyTimestampExtLibrary.java +++ b/logstash-core/src/main/java/org/logstash/ext/JrubyTimestampExtLibrary.java @@ -1,5 +1,6 @@ package org.logstash.ext; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.io.IOException; import org.jruby.Ruby; import org.jruby.RubyClass; @@ -19,6 +20,7 @@ import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.load.Library; import org.logstash.Timestamp; +import org.logstash.json.RubyTimestampSerializer; public class JrubyTimestampExtLibrary implements Library { @@ -40,6 +42,7 @@ public class JrubyTimestampExtLibrary implements Library { } @JRubyClass(name = "Timestamp") + @JsonSerialize(using = RubyTimestampSerializer.class) public static class RubyTimestamp extends RubyObject { private Timestamp timestamp; diff --git a/logstash-core/src/main/java/org/logstash/json/RubyTimestampSerializer.java b/logstash-core/src/main/java/org/logstash/json/RubyTimestampSerializer.java new file mode 100644 index 000000000..935db8dd8 --- /dev/null +++ b/logstash-core/src/main/java/org/logstash/json/RubyTimestampSerializer.java @@ -0,0 +1,22 @@ +package org.logstash.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import org.logstash.ext.JrubyTimestampExtLibrary; + +/** + * Serializer for {@link JrubyTimestampExtLibrary.RubyTimestamp} that serializes it exactly the same + * way {@link TimestampSerializer} serializes {@link org.logstash.Timestamp} to ensure consistent + * serialization across Java and Ruby representation of {@link org.logstash.Timestamp}. + */ +public final class RubyTimestampSerializer + extends JsonSerializer { + + @Override + public void serialize(final JrubyTimestampExtLibrary.RubyTimestamp value, + final JsonGenerator jgen, final SerializerProvider provider) throws IOException { + jgen.writeString(value.getTimestamp().toIso8601()); + } +} diff --git a/logstash-core/src/test/java/org/logstash/EventTest.java b/logstash-core/src/test/java/org/logstash/EventTest.java index efc8b8978..7059b6fee 100644 --- a/logstash-core/src/test/java/org/logstash/EventTest.java +++ b/logstash-core/src/test/java/org/logstash/EventTest.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.jruby.RubyTime; import org.junit.Test; import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals; @@ -106,6 +107,19 @@ public final class EventTest { assertJsonEquals("{\"@timestamp\":\"" + e.getTimestamp().toIso8601() + "\",\"foo\":{\"0\":{\"baz\":1}},\"@version\":\"1\"}", e.toJson()); } + @Test + public void testTimestampFieldToJson() throws Exception { + Event e = new Event(); + final RubyTime time = RubyUtil.RUBY.newTime(1000L); + e.setField("[foo][bar][baz]", time); + assertJsonEquals( + String.format( + "{\"@timestamp\":\"%s\",\"foo\":{\"bar\":{\"baz\":\"%s\"}},\"@version\":\"1\"}", + e.getTimestamp().toIso8601(), new Timestamp(time.getDateTime()).toIso8601() + ), e.toJson() + ); + } + @Test public void testGetFieldList() throws Exception { Map data = new HashMap<>();