@Override
    public ObjectNode encode(Host host, CodecContext context) {
        checkNotNull(host, NULL_OBJECT_MSG);

        final JsonCodec<HostLocation> locationCodec =
                context.codec(HostLocation.class);
        // keep fields in string for compatibility
        final ObjectNode result = context.mapper().createObjectNode()
                .put(HOST_ID, host.id().toString())
                .put(MAC, host.mac().toString())
                .put(VLAN, host.vlan().toString())
                .put(INNER_VLAN, host.innerVlan().toString())
                // use a 4-digit hex string in coding an ethernet type
                .put(OUTER_TPID, String.format("0x%04x", host.tpid().toShort()))
                .put(IS_CONFIGURED, host.configured())
                .put(IS_SUSPENDED, host.suspended());

        final ArrayNode jsonIpAddresses = result.putArray(IP_ADDRESSES);
        for (final IpAddress ipAddress : host.ipAddresses()) {
            jsonIpAddresses.add(ipAddress.toString());
        }
        result.set(IP_ADDRESSES, jsonIpAddresses);

        final ArrayNode jsonLocations = result.putArray(HOST_LOCATIONS);
        for (final HostLocation location : host.locations()) {
            jsonLocations.add(locationCodec.encode(location, context));
        }
        result.set(HOST_LOCATIONS, jsonLocations);

        if (host.auxLocations() != null) {
            final ArrayNode jsonAuxLocations = result.putArray(AUX_LOCATIONS);
            for (final HostLocation auxLocation : host.auxLocations()) {
                jsonAuxLocations.add(locationCodec.encode(auxLocation, context));
            }
            result.set(AUX_LOCATIONS, jsonAuxLocations);
        }

        return annotate(result, host, context);
    }
@Test
    public void testEncode() throws IOException {
        InputStream jsonStream = HostCodec.class.getResourceAsStream(JSON_FILE);
        JsonNode jsonString = context.mapper().readTree(jsonStream);

        ObjectNode expected = hostCodec.encode(HOST, context);
        // Host ID is not a field in Host but rather derived from MAC + VLAN.
        // Derived information should not be part of the JSON really.
        // However, we keep it as is for backward compatibility.
        expected.remove(HostCodec.HOST_ID);

        assertEquals(expected, jsonString);
    }