Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to sort mixed-type lists to JsonSlurper #58

Merged
merged 1 commit into from
Oct 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ Current

- [#45, removing sorting from weight check queries](https://github.com/yahoo/fili/pull/46)

- [`JsonSlurper` can now handle sorting lists with mixed-type entries](https://github.com/yahoo/fili/pull/58)
* even if the list starts with a string, number, or boolean

### Known Issues:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.
package com.yahoo.bard.webservice.util;

// Changed HashMap to LinkedHashMap for consistency. Added ability to optionally sort the lists and maps.

/*
* Changed HashMap to LinkedHashMap for consistency. Added ability to optionally sort the lists and maps.
* Copyright 2003-2014 the original author or authors.
*
* Licensed 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 com.yahoo.bard.webservice.util;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was borrowed from Groovy right? While we're here, we really should update the copyright notification to reflect that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

import static groovy.json.JsonTokenType.CLOSE_BRACKET;
import static groovy.json.JsonTokenType.CLOSE_CURLY;
import static groovy.json.JsonTokenType.COLON;
Expand All @@ -30,6 +45,8 @@
import java.util.TreeMap;

/**
* This is the original slurper included in case someone relies on its exact behavior.
*
* JSON slurper which parses text or reader content into a data structure of lists and maps.
* <p>
* Example usage:
Expand All @@ -50,7 +67,7 @@
@SuppressWarnings({ "rawtypes", "javadoc", "unchecked" })
public class JsonSlurper {

private final Comparator<Map> mapComparator;
private final Comparator<Object> variableTypedComparator;

private final JsonSortStrategy sortStrategy;

Expand All @@ -71,17 +88,17 @@ public JsonSlurper() {
* @param sortStrategy Strategy to use when sorting the parsed JSON object
*/
public JsonSlurper(JsonSortStrategy sortStrategy) {
this(sortStrategy, new ToStringComparator<Map>());
this(sortStrategy, new ToStringComparator<>());
}

/**
* Create a new JsonSlurper with the given sort strategy and map comparator.
*
* @param sortStrategy Strategy to use when sorting the parsed JSON object
* @param mapComparator Comparator to use when sorting a list of maps
* @param variableTypedComparator Comparator to use when sorting a list with variable types
*/
public JsonSlurper(JsonSortStrategy sortStrategy, Comparator<Map> mapComparator) {
this.mapComparator = mapComparator;
public JsonSlurper(JsonSortStrategy sortStrategy, Comparator<Object> variableTypedComparator) {
this.variableTypedComparator = variableTypedComparator;
this.sortStrategy = sortStrategy;
switch (sortStrategy) {
case SORT_BOTH:
Expand All @@ -103,8 +120,8 @@ public JsonSlurper(JsonSortStrategy sortStrategy, Comparator<Map> mapComparator)
}
}

public Comparator<Map> getMapComparator() {
return mapComparator;
public Comparator<Object> getVariableTypedComparator() {
return variableTypedComparator;
}

public JsonSortStrategy getSortStrategy() {
Expand All @@ -126,11 +143,16 @@ public boolean getSortMaps() {
*/
private void sortIfNeeded(List listToSort) {
if (sortLists) {
// Sort by the native compareTo if available, otherwise just sort by hash code to ensure consistent sorting
if (listToSort.size() > 0 && listToSort.get(0) instanceof Comparable) {
Collections.sort(listToSort);
// Sort by the native compareTo, otherwise just sort by the object comparator to ensure consistent sorting
if (listToSort.stream().anyMatch(it -> it instanceof Comparable)) {
try {
Collections.sort(listToSort);
} catch (ClassCastException ignored) {
// Failed to sort a consistently typed list of Comparables. Fall back to the collection comparator
Collections.sort(listToSort, variableTypedComparator);
}
} else {
Collections.sort(listToSort, mapComparator);
Collections.sort(listToSort, variableTypedComparator);
}
}
}
Expand Down