10

How do you send Json object's through sockets preferable through ObjectOutputStream class in java this is what I got so far

    s = new Socket("192.168.0.100", 7777);
    ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
    JSONObject object = new JSONObject();
    object.put("type", "CONNECT");
    out.writeObject(object);

But this gives an java.io.streamcorruptedexception exception any suggestions?

user3339626
  • 101
  • 1
  • 1
  • 3

2 Answers2

19

Instead of using ObjectOutputStream, you should create an OutputStreamWriter, then use that to write the JSON text to the stream. You need to choose an encoding - I would suggest UTF-8. So for example:

JSONObject json = new JSONObject();
json.put("type", "CONNECT");
Socket s = new Socket("192.168.0.100", 7777);
try (OutputStreamWriter out = new OutputStreamWriter(
        s.getOutputStream(), StandardCharsets.UTF_8)) {
    out.write(json.toString());
}
chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks for the pointer to `StandardCharsets`; I'd not run across the constants (which, IMHO, are in a stupid location). – chrylis -cautiouslyoptimistic- Feb 22 '14 at 12:37
  • UTF8 is the *only* byte encoding for JSON. Any other encoding and it's not legally JSON. – Hot Licks Feb 22 '14 at 12:46
  • 1
    @HotLicks: Interesting - where's that defined, just for my future reference? – Jon Skeet Feb 22 '14 at 13:03
  • In the standard: "JSON text is a sequence of Unicode code points". – Hot Licks Feb 22 '14 at 13:19
  • 1
    @HotLicks: that doesn't mean that these unicode code points must be encoded as UTF8. UTF8 is one of many ways to transform unicode code points to bytes. You could also use UTF16 or UTF32 for example. Isn't the encoding a property of the transport protocol (HTTP, most of the time)? – JB Nizet Feb 22 '14 at 14:39
  • I said "byte encoding". And the point is you'd never use ASCII or 8859_1 some non-UTF DBCS encoding. – Hot Licks Feb 22 '14 at 18:02
  • @HotLicks: But you could easily use UTF-16, or UTF-32... or you *could* use ISO-8859-1 if for some reason you knew that the JSON would never contain any data which isn't representable in that encoding. It does sound like claiming UTF-8 as the only valid encoding is simply incorrect. If JSON is a sequence of Unicode code points, how those are encoded as binary is a transport implementation detail. – Jon Skeet Feb 22 '14 at 18:06
  • But many parsers accept a byte stream (in fact, this is probably preferred), and if any multi-byte characters are encoded and the encoding is not UTF8 then you have problems. – Hot Licks Feb 22 '14 at 18:10
  • See http://www.ietf.org/rfc/rfc4627.txt: *JSON text SHALL be encoded in Unicode. The default encoding is UTF-8. Since the first two characters of a JSON text will always be ASCII characters [RFC0020], it is possible to determine whether an octet stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking at the pattern of nulls in the first four octets.* – JB Nizet Feb 22 '14 at 18:29
  • @HotLicks: If a parser accepts a byte stream, I'd expect it to also accept an encoding. It may *default* to UTF-8, but requiring that seems over the top. But this seems a very long way from your original position of claiming it's the *only* legal encoding for JSON. – Jon Skeet Feb 22 '14 at 18:30
  • @JBNizet: Excellent - thanks for the definitive reference. So there are multiple legal encodings compliant with RFC 4627, but UTF-8 is assumed by default. Makes sense - slightly stricter than XML, but still entirely reasonable. – Jon Skeet Feb 22 '14 at 18:31
  • Apple doesn't agree with you. The NSJSONSerialization kit for iPhone generates only UTF8 and accepts only UTF8/16/32 (with 8 strongly preferred). – Hot Licks Feb 22 '14 at 18:44
  • @HotLicks: Well, that just means Apple doesn't implement RFC 4627. That's not the same as claiming that JSON encoded using UTF-16 "isn't legal". Frankly UTF-8 would almost certainly be the best encoding to use in general, so I don't think we're arguing in terms of practicalities - but I wouldn't make a blanket statement like your original one. – Jon Skeet Feb 22 '14 at 18:46
  • How is Apple's kit not compliant? And I never said UTF-16 wasn't legal JSON. I said "byte encoding". UTF-16 is not "byte encoding". – Hot Licks Feb 22 '14 at 18:58
  • @HotLicks: Um, yes it is. What *exactly* do you understand by the term "byte encoding"? While I wouldn't use exactly that term, I'd understand it to be a conversion between Unicode code points and bytes. By that definition, UTF-16 is most *definitely* a byte encoding. (See System.Text.Encoding for example in .NET.) If you're using the term to mean something different, please give a precise definition. – Jon Skeet Feb 22 '14 at 19:00
  • @HotLicks: (To be more precise, there are two varieties of UTF-16 depending on endianness of the bytes. See http://www.unicode.org/faq/utf_bom.html for more about UTF-* encodings.) – Jon Skeet Feb 22 '14 at 19:06
  • Could you please explain why to use an OutputStreamWriter in stead of ObjectOutputStream? I know it's been a year, but I just came across this and was wondering why. – Daniel Jun 15 '16 at 12:15
  • 4
    @Daniel: Why would you want to wrap a nice portable format (JSON) in a Java-specific binary serialization format? – Jon Skeet Jun 15 '16 at 12:15
  • Jumping into this blast from the past, my read of the `OutputStreamWriter` documentation (https://docs.oracle.com/javase/7/docs/api/java/io/OutputStreamWriter.html) is that the `OutputStreamWriter` should be wrapped in a `BufferedWriter` "so as to avoid frequent converter invocations". The example given is `new BufferedWriter(new OutputStreamWriter(System.out))`. Is this still true and consistent with your collective experience? – Tom Stambaugh Mar 13 '23 at 16:40
  • 1
    @TomStambaugh: The documentation says to *consider* doing that, not that one *should* do that. In this case, there's only a single call to `write`, so the motivation of avoiding "frequent converter invocations" is irrelevant. – Jon Skeet Mar 13 '23 at 16:47
  • @JonSkeet: Indeed, absolutely. I appreciate your immediate and constructive response. I was looking at this in the context of a longer-lived service. I found a simpler and more direct alternative. – Tom Stambaugh Mar 14 '23 at 18:07
-2

An ObjectOutputStream writes primitive data types and graphs of Java objects to an OutputStream. The objects can be read (reconstituted) using an ObjectInputStream. Persistent storage of objects can be accomplished by using a file for the stream. If the stream is a network socket stream, the objects can be reconstituted on another host or in another process.

A data output stream lets an application write primitive Java data types to an output stream in a portable way. An application can then use a data input stream to read the data back in." You don't need to write primitive data types in binary, so do not use DataOutputStream

An OutputStreamWriter is a bridge from character streams to byte streams: Characters written to it are encoded into bytes using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted.

You need to create an OutputStreamWriter for sending json objects to the client

OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
JSONObject obj = new JSONObject();
obj.put("name", "harris");
obj.put("age", 23);
out.write(obj.toString());

You can read the output data from the client using InputStreamReader by this way

InputStreamReader input = new InputStreamReader(socket.getInputStream());
int data = input.read();
while (data != -1) {
    System.out.print((char)data);
    data = input.read();
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Deepak Silver
  • 27
  • 1
  • 3