sc-codec-min-bin icon indicating copy to clipboard operation
sc-codec-min-bin copied to clipboard

Fails to decode for JAVA client

Open AUT0CRAT opened this issue 8 years ago • 0 comments

SocketCluster works on a JSON object. I wrote my own codec for java with same that in the library. I need to refine it, but a working model is as follows,

@Override
public byte[] encode(JSONObject jsonObject) {
    MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
    ArrayList<Object> a = new ArrayList<>();
    Map<String, String[]> map = new HashMap<>();

    encodePublish(jsonObject, map);
    encodeEmit(jsonObject, map);
    encodeResponse(jsonObject, map);

    try {
        JSONObject toEncode = new JSONObject(map);
        packer.packString(toEncode.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return packer.toByteArray();
}

@Override
public byte[] encode(String data) {
    MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
    try {
        packer.packString(data);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return packer.toByteArray();
}

private void encodeResponse(JSONObject jsonObject, Map<String, String[]> map) {
    String rid = jsonObject.optString("rid", null);
    if (rid == null) {
        return;
    }

    List<String> a = new ArrayList<>();
    a.add(rid);
    a.add(jsonObject.optString("error"));
    String cid = jsonObject.optString("data");
    if (cid != null) {
        a.add(cid);
    }

    map.put("r", a.toArray(new String[]{}));

    jsonObject.remove("rid");
    jsonObject.remove("error");
    jsonObject.remove("data");
}


private void encodeEmit(JSONObject jsonObject, Map<String, String[]> map) {
    String event = jsonObject.optString("event", null);
    if (event == null) {
        return;
    }

    List<String> a = new ArrayList<>();
    a.add(jsonObject.optString("event"));
    a.add(jsonObject.optString("data"));
    String cid = jsonObject.optString("cid");
    if (cid != null) {
        a.add(cid);
    }

    map.put("e", a.toArray(new String[]{}));

    jsonObject.remove("event");
    jsonObject.remove("data");
    jsonObject.remove("cid");
}

private void encodePublish(JSONObject jsonObject, Map<String, String[]> map) {
    String event = jsonObject.optString("event", null);
    if (event == null || !event.equals("#publish")) {
        return;
    }

    List<String> a = new ArrayList<>();
    a.add(jsonObject.optString("channel"));
    a.add(jsonObject.optString("data"));
    String cid = jsonObject.optString("cid");
    if (cid != null) {
        a.add(cid);
    }
    map.put("p", a.toArray(new String[]{}));

    jsonObject.remove("event");
    jsonObject.remove("data");
    jsonObject.remove("cid");

}

@Override
public String decode(byte[] data) {
    MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(data);
    try {
        ImmutableValue mapValue = unpacker.unpackValue();
        try {
            JSONObject object = new JSONObject(mapValue.toString());
            decodeEmit(object);
            decodePublish(object);
            decodeResponse(object);
            return object.toString();
        } catch (JSONException e) {
            return mapValue.toString();
        }


    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

private void decodePublish(JSONObject object) {
    JSONArray p = object.optJSONArray("p");
    if (p == null) {
        return;
    }

    try {
        object.put("event", "#publish");
        JSONObject data = new JSONObject();
        int size = p.length();
        data.put("channel", p.get(0));
        data.put("data", p.get(1));
        if (size > 2) {
            data.put("cid", p.get(2));
        }
        object.put("data", data);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    object.remove("p");
}

private void decodeEmit(JSONObject object) {
    JSONArray e = object.optJSONArray("e");
    if (e == null) {
        return;
    }

    try {
        object.put("event", e.get(0));
        object.put("data", e.get(1));

        if (e.length() > 2) {
            object.put("cid", e.get(2));
        }
    } catch (JSONException ex) {
        ex.printStackTrace();
    }

    object.remove("e");
}

private void decodeResponse(JSONObject object) {
    JSONArray r = object.optJSONArray("r");
    if (r == null) {
        return;
    }

    try {
        object.put("rid", r.get(0));
        object.put("error", r.get(1));
        object.put("data", r.get(2));
    } catch (JSONException e) {
        e.printStackTrace();
    }

    object.remove("r");
}

Now the issue is that, when i emit my data, the server receives the data as a string and not an object, hence the data is never decoded. The decompressSinglePacket fails as the data is in string format and not a JavaScript Object.

Maybe we need to add an explicit JSON.parse so that the data is converted to a Javascript object and then the flow will be executed?

AUT0CRAT avatar Nov 23 '17 09:11 AUT0CRAT