diff --git a/CHANGES.txt b/CHANGES.txt index 10258d2b54e..18f319b10b3 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -237,6 +237,8 @@ Bug Fixes 14. The CSV loader incorrectly threw an exception when given header=true (the default). (ryan, yonik) +15. SOLR-449: the python and ruby response writers are now able to correctly + output NaN and Infinity in their respective languages. (klaas) Other Changes 1. SOLR-135: Moved common classes to org.apache.solr.common and altered the diff --git a/src/java/org/apache/solr/request/JSONResponseWriter.java b/src/java/org/apache/solr/request/JSONResponseWriter.java index 67fbdc936e2..0eb4477b44e 100644 --- a/src/java/org/apache/solr/request/JSONResponseWriter.java +++ b/src/java/org/apache/solr/request/JSONResponseWriter.java @@ -689,3 +689,39 @@ class JSONWriter extends TextResponseWriter { } } + +abstract class NaNFloatWriter extends JSONWriter { + + abstract protected String getNaN(); + abstract protected String getInf(); + + public NaNFloatWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) { + super(writer, req, rsp); + } + + @Override + public void writeFloat(String name, float val) throws IOException { + if (Float.isNaN(val)) { + writer.write(getNaN()); + } else if (Float.isInfinite(val)) { + if (val < 0.0f) + writer.write('-'); + writer.write(getInf()); + } else { + writeFloat(name, Float.toString(val)); + } + } + + @Override + public void writeDouble(String name, double val) throws IOException { + if (Double.isNaN(val)) { + writer.write(getNaN()); + } else if (Double.isInfinite(val)) { + if (val < 0.0) + writer.write('-'); + writer.write(getInf()); + } else { + writeDouble(name, Double.toString(val)); + } + } +} \ No newline at end of file diff --git a/src/java/org/apache/solr/request/PythonResponseWriter.java b/src/java/org/apache/solr/request/PythonResponseWriter.java index 98a0665d923..742e60df598 100644 --- a/src/java/org/apache/solr/request/PythonResponseWriter.java +++ b/src/java/org/apache/solr/request/PythonResponseWriter.java @@ -43,7 +43,10 @@ public class PythonResponseWriter implements QueryResponseWriter { } } -class PythonWriter extends JSONWriter { +class PythonWriter extends NaNFloatWriter { + protected String getNaN() { return "float('NaN')"; } + protected String getInf() { return "float('Inf')"; } + public PythonWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) { super(writer, req, rsp); } diff --git a/src/java/org/apache/solr/request/RubyResponseWriter.java b/src/java/org/apache/solr/request/RubyResponseWriter.java index c010513d711..c16f5389cf2 100644 --- a/src/java/org/apache/solr/request/RubyResponseWriter.java +++ b/src/java/org/apache/solr/request/RubyResponseWriter.java @@ -42,7 +42,11 @@ public class RubyResponseWriter implements QueryResponseWriter { } } -class RubyWriter extends JSONWriter { +class RubyWriter extends NaNFloatWriter { + + protected String getNaN() { return "(0.0/0.0)"; } + protected String getInf() { return "(1.0/0.0)"; } + public RubyWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) { super(writer, req, rsp); } diff --git a/src/test/org/apache/solr/request/JSONWriterTest.java b/src/test/org/apache/solr/request/JSONWriterTest.java new file mode 100644 index 00000000000..ddf995ec2e1 --- /dev/null +++ b/src/test/org/apache/solr/request/JSONWriterTest.java @@ -0,0 +1,54 @@ +/** + * 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.solr.request; + +import java.io.IOException; +import java.io.Writer; +import java.io.StringWriter; + +import org.apache.solr.common.util.NamedList; +import org.apache.solr.util.AbstractSolrTestCase; + +/** Test some aspects of JSON/python writer output (very incomplete) + * + */ +public class JSONWriterTest extends AbstractSolrTestCase { + + public String getSchemaFile() { return "schema.xml"; } + public String getSolrConfigFile() { return "solrconfig.xml"; } + + public void testNaNInf() throws IOException { + SolrQueryRequest req = req("dummy"); + SolrQueryResponse rsp = new SolrQueryResponse(); + QueryResponseWriter w = new PythonResponseWriter(); + + StringWriter buf = new StringWriter(); + rsp.add("data1", Float.NaN); + rsp.add("data2", Double.NEGATIVE_INFINITY); + rsp.add("data3", Float.POSITIVE_INFINITY); + w.write(buf, req, rsp); + assertEquals(buf.toString(), "{'data1':float('NaN'),'data2':-float('Inf'),'data3':float('Inf')}"); + + w = new RubyResponseWriter(); + buf = new StringWriter(); + w.write(buf, req, rsp); + assertEquals(buf.toString(), "{'data1'=>(0.0/0.0),'data2'=>-(1.0/0.0),'data3'=>(1.0/0.0)}"); + + } + +}