Skip to content

Commit

Permalink
Make JsonUtils serialize Instant always with the same format
Browse files Browse the repository at this point in the history
patch by Stefan Miklosovic; reviewed by Maxim Muzafarov for CASSANDRA-20209
  • Loading branch information
smiklosovic committed Jan 17, 2025
1 parent 2a3454a commit 6e8d0cd
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
5.1
* Make JsonUtils serialize Instant always with the same format (CASSANDRA-20209)
* Port Harry v2 to trunk (CASSANDRA-20200)
* Enable filtering of snapshots on keyspace, table and snapshot name in nodetool listsnapshots (CASSANDRA-20151)
* Create manifest upon loading where it does not exist or enrich it (CASSANDRA-20150)
Expand Down
19 changes: 16 additions & 3 deletions src/java/org/apache/cassandra/utils/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -29,8 +32,8 @@
import com.fasterxml.jackson.core.util.BufferRecyclers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer;
import org.apache.cassandra.io.util.File;
import org.apache.cassandra.io.util.FileInputStreamPlus;
import org.apache.cassandra.io.util.FileOutputStreamPlus;
Expand All @@ -44,10 +47,20 @@ public final class JsonUtils
public static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper(new JsonFactory()); // checkstyle: permit this instantiation
public static final ObjectWriter JSON_OBJECT_PRETTY_WRITER;

private static class GlobalInstantSerializer extends InstantSerializer
{
private GlobalInstantSerializer()
{
super(InstantSerializer.INSTANCE,
false,
false,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC));
}
}

static
{
JSON_OBJECT_MAPPER.registerModule(new JavaTimeModule());
JSON_OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
JSON_OBJECT_MAPPER.registerModule(new JavaTimeModule().addSerializer(Instant.class, new GlobalInstantSerializer()));
JSON_OBJECT_PRETTY_WRITER = JSON_OBJECT_MAPPER.writerWithDefaultPrettyPrinter();
}

Expand Down
5 changes: 2 additions & 3 deletions test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,8 @@ private void testTrueSnapshotSizeInternal(String keyspace, String table, boolean
long anotherWithIndexSize = listedSnapshots.get("snapshot2_with_index").computeSizeOnDiskBytes();
long anotherWithIndexTrueSize = listedSnapshots.get("snapshot2_with_index").computeTrueSizeBytes();

// TODO CASSANDRA-20209
assertTrue(withIndexSize == anotherWithIndexSize || (withIndexSize + 4 == anotherWithIndexSize) || (withIndexSize - 4 == anotherWithIndexSize));
assertTrue(withIndexTrueSize == anotherWithIndexTrueSize || (withIndexTrueSize + 4 == anotherWithIndexTrueSize) || (withIndexTrueSize - 4 == anotherWithIndexTrueSize));
assertEquals(withIndexSize, anotherWithIndexSize);
assertEquals(withIndexTrueSize, anotherWithIndexTrueSize);
}

private void rebuildIndices(ColumnFamilyStore cfs)
Expand Down
36 changes: 36 additions & 0 deletions test/unit/org/apache/cassandra/utils/JsonUtilsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.cassandra.utils;

import org.junit.Test;

import static java.time.Instant.parse;
import static org.apache.cassandra.utils.JsonUtils.writeAsJsonString;
import static org.junit.Assert.assertEquals;

public class JsonUtilsTest
{
@Test
public void testTimestampSerialisation()
{
assertEquals("\"2025-01-15T13:26:45.040Z\"", writeAsJsonString(parse("2025-01-15T13:26:45.04Z")));
assertEquals("\"2025-01-15T13:26:45.100Z\"", writeAsJsonString(parse("2025-01-15T13:26:45.1Z")));
assertEquals("\"2025-01-15T13:26:45.123Z\"", writeAsJsonString(parse("2025-01-15T13:26:45.123Z")));
}
}

0 comments on commit 6e8d0cd

Please sign in to comment.