Don't serialize fields if it exists further up the tree - jackson

Lots of my domain objects have a unit field. Currently when I serialize, every object outputs the unit field:
{
"projects": [
{
"name": "project1",
"unit": "mm",
"size": {
"x": {
"value": 100,
"unit": "mm"
},
"y": {
"value": 120,
"unit": "mm"
},
"z": {
"value": 80,
"unit": "mm"
}
},
"materials": [
{
"type": "wood",
"unit": "mm",
"size": {
"x": {
"value": 100,
"unit": "mm"
},
"y": {
"value": 120,
"unit": "mm"
},
"z": {
"value": 80,
"unit": "mm"
}
}
},
...
]
},
...
]
}
I need the individual objects to have the unit property, because they are sometimes serialized on their own. e.g.
{
"length": {
"value": 100,
"unit": "mm"
}
}
But when it is nested in another object that already specifies the unit, it leads to an awful lot of duplication.
How can I get jackson to omit the unit field if there is already a unit field with the same value somewhere further up the tree?
Here are some example outputs I want to achieve using the same instances but just changing what the root object of the serialization is:
{
"projects": [
{
"name": "project1",
"unit": "mm",
"size": {
"x": {
"value": 100
},
"y": {
"value": 120
},
"z": {
"value": 80
}
},
"materials": [
{
"type": "wood",
"size": {
"x": {
"value": 100
},
"y": {
"value": 120
},
"z": {
"value": 80
}
}
},
...
]
},
...
]
}
{
"type": "wood",
"unit": "mm",
"size": {
"x": {
"value": 100
},
"y": {
"value": 120
},
"z": {
"value": 80
}
}
}
{
"value": 100,
"unit": "mm"
}

AFAIK you can’t add business logic like that in the parser.
You’ll have to massage the data class before the mapper.

Related

How to follow make a dot and text follow a mouse?

To get to know how events work in VEGA, I gave myself the simple exercice to render a dot and a text positioned on the cursors coordinates in a given view.
I managed to make a symbol follow the mouse coordinates, yet when I try to make two types of marks ( text and symbol) follow the mouse , it doesn't render them both but the first one appearing in the marks [ ] array.
Any ideas ?
Following specification is used in the exercice :
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 600,
"height": 600,
"signals": [
{
"name": "position",
"on": [
{
"events": {
"type": "mousemove"
},
"update": "xy()"
}
]
},
{
"name": "positionDot",
"on": [
{
"events": {
"type": "mousemove"
},
"update": "xy()"
}
]
}
],
"marks": [
{
"type": "text",
"encode": {
"enter": {
"fill": {
"value": "#000"
},
"text": {
"value": "Text Label"
}
},
"update": {
"opacity": {
"value": 1
},
"x": {
"signal": "position[0]+20"
},
"y": {
"signal": "position[1]+20"
},
"fontSize": {
"value": 50
}
}
}
},
{
"name": "dot",
"type": "symbol",
"encode": {
"enter": {
"fill": {
"value": "#939597"
},
"stroke": {
"value": "#652c90"
},
"x": {
"value": 0
},
"y": {
"value": 0
}
},
"update": {
"x": {
"signal": "positionDot[0]"
},
"y": {
"signal": "position[1]"
},
"size": {
"value": 550
},
"opacity": {
"value": 1
}
},
"hover": {
"opacity": {
"value": 0.5
}
}
}
}
]
}
https://vega.github.io/editor/#/gist/1dcd1034a1d8139b3de49f041ed1ed4b/spec.json
Your example works as expected if an initial value (using "init" or "value") is included in signal position:
"signals": [
{
"name": "position",
"init": [0, 0],
"on": [
{
"events": {
"type": "mousemove"
},
"update": "xy()"
}
]
},
View in Vega online editor

Why column facet in Vega Lite not working properly with layer?

I'm trying to create 3 column plot and it works when there's no layer.
But when I add the layer - 3 columns get merged into one plot (open in editor).
How to make it to be separated into 3 columns by the duration field?
CODE
For the plot with the full data please use editor link above.
{
"encoding": {
"column": { "field": "duration", "type": "nominal" },
"x": { "field": "bin_i", "type": "ordinal" }
},
"layer": [
{
"mark": { "type": "bar", "size": 2 },
"encoding": {
"y": { "field": "min", "type": "quantitative" },
"y2": { "field": "max", "type": "quantitative" }
}
},
{
"mark": { "type": "tick" },
"encoding": {
"y": { "field": "mean", "type": "quantitative" }
}
}
],
"data": {
"values": [
{
"bin_i": 1,
"duration": 1,
"max": 1.9642835793718165,
"mean": 1.0781367168962268,
"min": 0.3111818864927448
},
...
]
}
}
A layered chart does not accept a faceted encoding. If you want to facet a layered chart, you should use the facet operator rather than a facet encoding.
For your example, it would look like this (Vega Editor):
{
"facet": {"column": {"field": "duration", "type": "nominal"}},
"spec": {
"encoding": {
"x": {"field": "bin_i", "type": "ordinal"}
},
"layer": [
{
"mark": {"type": "bar", "size": 2},
"encoding": {
"y": {"field": "min", "type": "quantitative"},
"y2": {"field": "max"}
}
},
{
"mark": {"type": "tick"},
"encoding": {
"y": {"field": "mean", "type": "quantitative"}
}
}
]
},
"data": {
"values": [
{
"bin_i": 1,
"duration": 1,
"max": 1.9642835793718165,
"mean": 1.0781367168962268,
"min": 0.3111818864927448
},
...
]
}
}

How to specify Rule Line with a single value in VegaLite?

It's possible to specify Rule as encoding over the data. But sometimes it's too verbose. Is there a shorter way to specify it with just a single number?
In example below I want to draw a horizontal line with y=1 and it requires me to specify a calculate transform. Wonder if it's possible with something more compact, like:
"layer": [
...,
{ "mark": { "type": "rule", "y": 1 }, // Specify ruler with just a single line
...
]
Playground
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"transform":[
{ "calculate": "1", "as": "one" }
],
"layer": [
{
"mark": { "type": "bar" },
"encoding": {
"x": { "field": "diff", "type": "quantitative" },
"y": { "field": "diff", "type": "quantitative" }
}
},
{
"mark": { "type": "rule" },
"encoding": {
"y": { "field": "one", "type": "quantitative" }
}
}
],
"data": {
"values": [
{ "diff": 1 },
{ "diff": 2 },
{ "diff": 3 }
]
}
}
You can specify a single value using the "value" field in the encoding; e.g.
{
"mark": { "type": "rule" },
"encoding": {
"y": { "value": 133 }
}
}
(Playground)
But be aware this value is a value in the axis domain, rather than in the data domain; i.e. it represents pixels from the top-left of the chart.
If you want to specify a value in the data domain, there is no such shorthand. You have to either use a transform (as you did in your question) or define a new dataset for your layer. The most compact way of doing this, I think, is something like this:
{
"mark": { "type": "rule" },
"data": {"values": {"y": 1}},
"encoding": {
"y": { "field": "y" }
}
}

How to change color of stroke in Parallel Coordinate Vega Chart?

I'm working with vega charts (parallel coordinates). How do I change the color of the lines with respect to scheme colors (w.r.t 'name' field).
Here is my code
I tried changing the stroke property with color scale but there is no effect on line stroke.
Can anyone point out what am I doing wrong.
I'm using Vega Version 4
Thanks
vikky
Because the colors need to be by column "name", transform the input dataset to have repeated name rows. In other words, input dataset must be of 3 columns (name, quarter, value)
Then, change "group" type mark to use facet dataset grouped by column "name"
"name": "marks_group_lines",
"type": "group",
"from": {
"facet": {
"name": "cars_by_name",
"data": "cars",
"groupby": "name"
}
},
Use the cars_by_name as dataset to render "line" type mark.
tip: Instead of defining quarter dataset for 4 axes for each qarter and scales for these axes, "line" type mark which has point scale for "x" property can be used.
Full code for reference:
{
"$schema": "https://vega.github.io/schema/vega/v4.json",
"width": 700,
"height": 400,
"padding": 5,
"config": {
"axisY": {
"titleX": -2,
"titleY": 410,
"titleAngle": 0,
"titleAlign": "right",
"titleBaseline": "top"
}
},
"data": [
{
"name": "cars",
"values": [
{
"name": "A",
"quarter": "Q1",
"value": 51
},
{
"name": "A",
"quarter": "Q2",
"value": 47
},
{
"name": "A",
"quarter": "Q3",
"value": 45
},
{
"name": "A",
"quarter": "Q4",
"value": 30
},
{
"name": "B",
"quarter": "Q1",
"value": 42
},
{
"name": "B",
"quarter": "Q2",
"value": 57
},
{
"name": "B",
"quarter": "Q3",
"value": 72
},
{
"name": "B",
"quarter": "Q4",
"value": 41
},
{
"name": "C",
"quarter": "Q1",
"value": 25
},
{
"name": "C",
"quarter": "Q2",
"value": 37
},
{
"name": "C",
"quarter": "Q3",
"value": 60
},
{
"name": "C",
"quarter": "Q4",
"value": 25
},
{
"name": "D",
"quarter": "Q1",
"value": 22
},
{
"name": "D",
"quarter": "Q2",
"value": 25
},
{
"name": "D",
"quarter": "Q3",
"value": 51
},
{
"name": "D",
"quarter": "Q4",
"value": 42
}
]
},
{
"name": "fields",
"values": [
"Q1",
"Q2",
"Q3",
"Q4"
]
}
],
"scales": [
{
"name": "name_to_xaxis",
"type": "point",
"domain": {
"data": "cars",
"field": "quarter"
},
"range": "width"
},
{
"name": "values_to_height",
"type": "linear",
"domain": {
"data": "cars",
"field": "value"
},
"range": "height"
},
{
"name": "quarter_to_color",
"type": "ordinal",
"domain": {
"data": "cars",
"field": "name"
},
"range": "category"
},
{
"name": "ord",
"type": "point",
"range": "width",
"round": true,
"domain": {
"data": "fields",
"field": "data"
}
},
{
"name": "Q1",
"type": "linear",
"range": "height",
"zero": false,
"nice": true,
"domain": {
"data": "cars",
"field": "Q1"
}
},
{
"name": "Q2",
"type": "linear",
"range": "height",
"zero": false,
"nice": true,
"domain": {
"data": "cars",
"field": "Q2"
}
},
{
"name": "Q3",
"type": "linear",
"range": "height",
"zero": false,
"nice": true,
"domain": {
"data": "cars",
"field": "Q3"
}
},
{
"name": "Q4",
"type": "linear",
"range": "height",
"zero": false,
"nice": true,
"domain": {
"data": "cars",
"field": "Q4"
}
}
],
"axes": [
{
"orient": "left",
"zindex": 1,
"scale": "Q1",
"title": "Q1",
"ticks": false,
"labels": false,
"offset": {
"scale": "ord",
"value": "Q1",
"mult": -1
}
},
{
"orient": "left",
"zindex": 1,
"scale": "Q2",
"title": "Q2",
"ticks": false,
"labels": false,
"offset": {
"scale": "ord",
"value": "Q2",
"mult": -1
}
},
{
"orient": "left",
"zindex": 1,
"scale": "Q3",
"title": "Q3",
"ticks": false,
"labels": false,
"offset": {
"scale": "ord",
"value": "Q3",
"mult": -1
}
},
{
"orient": "left",
"zindex": 1,
"scale": "Q4",
"title": "Q4",
"ticks": false,
"labels": false,
"offset": {
"scale": "ord",
"value": "Q4",
"mult": -1
}
}
],
"marks": [
{
"name": "marks_group_lines",
"type": "group",
"from": {
"facet": {
"name": "cars_by_name",
"data": "cars",
"groupby": "name"
}
},
"marks": [
{
"name": "marks_lines",
"type": "line",
"from": {
"data": "cars_by_name"
},
"encode": {
"update": {
"x": {
"scale": "name_to_xaxis",
"field": "quarter"
},
"y": {
"scale": "values_to_height",
"field": "value"
},
"stroke": {
"scale": "quarter_to_color",
"field": "name"
},
"strokeOpacity": {
"value": 1
}
},
"hover": {
"stroke": {
"value": "#7c7c7c"
},
"strokeOpacity": {
"value": 1
},
"zindex": 99
}
}
},
{
"name": "marks_symbols",
"type": "symbol",
"from": {
"data": "cars_by_name"
},
"encode": {
"enter": {
"stroke": {
"value": "#6D6D6D"
},
"strokeWidth": {
"value": 1
},
"shape": {
"value": "circle"
}
},
"update": {
"x": {
"scale": "name_to_xaxis",
"field": "quarter"
},
"y": {
"scale": "values_to_height",
"field": "value"
},
"fill": {
"scale": "quarter_to_color",
"field": "name"
},
"size": {
"value": 50
},
"stroke": {
"value": "#77AE80"
}
},
"hover": {
"fill": {
"value": "#AFD098"
}
}
}
}
]
}
]
}

How to add legend for single or multi series chart in Vega Lite?

How do I add a legend to a basic chart in Vega?
I'm using Vega in the web app where I want all my charts to include a legend even if its a single series.
i.e in Google Sheets it looks like
Since Datum hasn't been implemented yet I added an extra layer as a workaround (This also works for Multi Series Charts by adding additional values into data.values for the rule.)
{
"mark": {
"type": "rule"
},
"data": {
"values": [
{
"color": "Total Units"
}
]
},
"encoding": {
"color": {
"field": "color",
// If you want to update the color of the legend...
"scale": {"range": ["blue", "#000"]},
"sort": false,
"type": "nominal",
"legend": { "title": "" }
}
}
}
Also for those that want to view an example in VegaLite Editor https://vega.github.io/editor/#/
{
"layer": [
{
"mark": "bar",
"data": {
"values": [
{
"goal": 25,
"project": "a",
"score": 25
},
{
"goal": 47,
"project": "b",
"score": 57
},
{
"goal": 30,
"project": "c",
"score": 23
},
{
"goal": 27,
"project": "d",
"score": 19
}
]
},
"encoding": {
"x": {
"type": "nominal",
"field": "project"
},
"y": {
"type": "quantitative",
"field": "score"
}
},
"height": 300,
"width": 400
},
{
"mark": {
"type": "rule"
},
"data": {
"values": [
{
"color": "Goal"
}
]
},
"encoding": {
"color": {
"field": "color",
"sort": false,
"type": "nominal",
"legend": { "title": "" }
}
}
}
]
}