定义Java POJO,这样Gson就不会写双引号

时间:2017-06-05 13:10:25

标签: javascript java gson

注意这个例子是javascript

<html>
<head>
<script type="text/javascript">
window.onload = function () {
    var chart = new CanvasJS.Chart("chartContainer",
    {
        title: {
            text: "Using labelFormatter function of axisY"
        },
        axisY:{
            labelFormatter: function(e){
                return  "Y: " + e.value;
            }
        },
        data: [
        {
            type: "spline",          
            dataPoints: [
                { y: 5  }, 
                { y: 9  }, 
                { y: 17 }, 
                { y: 32 }, 
                { y: 22 }, 
                { y: 14 }, 
                { y: 25 }, 
                { y: 18 }, 
                { y: 20 }
            ]
        }
        ]          
    });
    chart.render();
}
</script>
<script type="text/javascript" src="/assets/script/canvasjs.min.js"></script>
</head>
<body>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
</body>
</html>

来自http://canvasjs.com/docs/charts/chart-options/axisy/label-formatter/,标签格式字段的值不是双引号,如果我将其修改为双引号,则代码不起作用。

我不明白Javascript规则什么时候它是shoud /不是双引号但似乎功能一定不是。

我正在尝试使用Gson从Java生成此类代码,如何创建我的POJO,以便在输出到json时不会将其值引用为双引号。目前它只是被定义为String类型,因此被双引号。

e.g

public class AxisY
{
    private boolean reversed;
    private int     labelMaxWidth;
    private boolean labelWrap;
    private String  title;
    private int     viewportMinimum = 0;
    private int     viewportMaximum;
    private int     interval;
    private String  labelFormatter;


    public boolean isReversed()
    {
        return reversed;
    }

    public void setReversed(boolean reversed)
    {
        this.reversed = reversed;
    }

    public int getLabelMaxWidth()
    {
        return labelMaxWidth;
    }

    public void setLabelMaxWidth(int labelMaxWidth)
    {
        this.labelMaxWidth = labelMaxWidth;
    }

    public boolean isLabelWrap()
    {
        return labelWrap;
    }

    public void setLabelWrap(boolean labelWrap)
    {
        this.labelWrap = labelWrap;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public int getViewportMinimum()
    {
        return viewportMinimum;
    }

    public void setViewportMinimum(int viewportMinimum)
    {
        this.viewportMinimum = viewportMinimum;
    }

    public int getViewportMaximum()
    {
        return viewportMaximum;
    }

    public void setViewportMaximum(int viewportMaximum)
    {
        this.viewportMaximum = viewportMaximum;
    }

    public int getInterval()
    {
        return interval;
    }

    public void setInterval(int interval)
    {
        this.interval = interval;
    }

    public String getLabelFormatter()
    {
        return labelFormatter;
    }

    public void setLabelFormatter(String labelFormatter)
    {
        this.labelFormatter = labelFormatter;
    }
}




  <!DOCTYPE HTML>
    <html>
    <head>
    <script type="text/javascript">
    window.onload = function () {
        var chart = new CanvasJS.Chart("chartContainer",
        {
            title: {
                text: "Using labelFormatter function of axisY"
            },
            axisY:{
                labelFormatter: function(e){
                    return  "Y: " + e.value;
                }
            },
            data: [
            {
                type: "spline",          
                dataPoints: [
                    { y: 5  }, 
                    { y: 9  }, 
                    { y: 17 }, 
                    { y: 32 }, 
                    { y: 22 }, 
                    { y: 14 }, 
                    { y: 25 }, 
                    { y: 18 }, 
                    { y: 20 }
                ]
            }
            ]          
        });
        chart.render();
    }
    </script>
    <script type="text/javascript" src="/assets/script/canvasjs.min.js"></script>
    </head>
    <body>
    <div id="chartContainer" style="height: 300px; width: 100%;"></div>
    </body>
    </html>

4 个答案:

答案 0 :(得分:2)

Gson正在将您的Java POJO序列化为JSON。 JSON不支持函数值。 JSON支持的值类型是object,array,string,boolean和number。

答案 1 :(得分:1)

  

我不明白Javascript规则什么时候它是shoud /不是双引号但似乎功能一定不是。

您正在混合使用JavaScript代码和JavaScript Object Notation(JSON)。 JSON中不存在函数(参见其grammar),后者仅提供数据持久性/转移职责(正是jjones建议的那样)。因此,Gson将所有字符串视为字符串文字 - 这就是为什么你要让你的function - 包含字符串进行转义。这是它应该工作的方式。

安全问题

我不推荐的另一件事是直接在JSON中传输JavaScript代码。这是一个明显的安全问题。我最好将labelFormatter值作为简单名称传递,让前端代码按名称选择正确的函数(如果有人将labelFormatter作为function(){stealSessionCookies();}发送,会怎么样?)。说,

(来自服务器)

{
    "axisY": {
        "labelFormatterStyleName": "y-by-name"
    }
}

(在客户端类似的东西)

var labelFormatterStyles = {
    "y-by-name": function(e) {
        return "Y: " + e.value;
    }
}

var chartConfiguration = { // or something more JS-idiomatic to avoid field-by-field assignments
                           // I didn't write in JS for long time
    axisY: {
        labelFormatter: labelFormatterStyles[serverResponse.labelFormatterStyleName]
    }
};
new CanvasJS.Chart("chartContainer", chartConfiguration);

如果你仍然坚信要用Gson

做这件事

如果由于任何坚实的原因你仍然需要在服务器端生成这样的东西,你可以调整你的Gson以发出“更像JavaScript的代码”。

final class ChartData {

    final Title title;
    final Axis axisY;
    final List<Datum> data;

    ChartData(final Title title, final Axis axisY, final List<Datum> data) {
        this.title = title;
        this.axisY = axisY;
        this.data = data;
    }

}
final class Title {

    final String text;

    Title(final String text) {
        this.text = text;
    }

}
final class Axis {

    @JsonAdapter(RawStringTypeAdapter.class)
    final String labelFormatter;

    Axis(final String labelFormatter) {
        this.labelFormatter = labelFormatter;
    }

}
final class Datum {

    final String type;
    final List<DataPoint> dataPoints;

    Datum(final String type, final List<DataPoint> dataPoints) {
        this.type = type;
        this.dataPoints = dataPoints;
    }

}
final class DataPoint {

    final double y;

    DataPoint(final double y) {
        this.y = y;
    }

}

请注意,Axis类的字段标注为@JsonAdapter(RawStringTypeAdapter.class)。这是一个特殊的指令,告诉Gson应用特殊(de)序列化策略。我们可以绑定一个来发出原始字符串值。例如:

final class RawStringTypeAdapter
        extends TypeAdapter<String> {

    // Gson can do it itself    
    private RawStringTypeAdapter() {
    }

    @Override
    public void write(final JsonWriter out, final String value)
            throws IOException {
        // not out.value(value)!
        out.jsonValue(value);
    }

    @Override
    public String read(final JsonReader in)
            throws IOException {
        return in.nextString();
    }

}

测试:

final ChartData chartData = new ChartData(
        new Title("Using labelFormatter function of axisY"),
        new Axis(
                "function(e) { return \"Y: \" + e.value; }"
        ),
        ImmutableList.of(
                new Datum(
                        "spline",
                        ImmutableList.of(
                                new DataPoint(5),
                                new DataPoint(9),
                                new DataPoint(17),
                                new DataPoint(32),
                                new DataPoint(22),
                                new DataPoint(14),
                                new DataPoint(25),
                                new DataPoint(18),
                                new DataPoint(20)
                        )
                )
        )
);
gson.toJson(chartData, System.out);

输出(部分缩小矿井):

{
  "title": {
    "text": "Using labelFormatter function of axisY"
  },
  "axisY": {
    "labelFormatter": function(e) { return "Y: " + e.value; }
  },
  "data": [
    {
      "type": "spline",
      "dataPoints": [
        {"y": 5.0},
        {"y": 9.0},
        {"y": 17.0},
        {"y": 32.0},
        {"y": 22.0},
        {"y": 14.0},
        {"y": 25.0},
        {"y": 18.0},
        {"y": 20.0}
      ]
    }
  ]
}

但是,我不建议您在后端生成JavaScript代码:除安全问题外,更改和重新部署JavaScript代码更容易。

答案 2 :(得分:0)

您可以发送JSON双引号,就像它应该是,并且您使用此库https://github.com/jcoc611/cassandraMAP

cassandraMAP.stringify({"key": "value"}); // => "{'key':'value'}"
cassandraMAP.parse("{'key':'value'}"); // => {"key": "value"}

答案 3 :(得分:0)

将labelFormatter函数作为字符串传递,在你的js中你需要在这个值中放入一个eval:

labelFormatter: eval("("+ <yourFunctionAsString> +")");