On Thu, May 11, 2017 at 9:30 AM, Jeff Schnitzer <[email protected]> wrote: > This is just one programmer’s opinion: > > * ObjectReader and ObjectWriter are not great as the “master” object; I > need both of them, which means I would need to pass around two variables > everywhere. It would be better to have an ObjectReaderWriter.
I understand, but this is problematic since such an object is fundamentally unwieldy... (I have considered this; and maybe something could be done) > * The performance of creating new ObjectMappers can be pretty easily > understood as “it’s best to re-use objectmappers”. I think people understand > that and making a more convenient configuration API wouldn’t hurt. I believe > from observation that it’s pretty common for people to new > ObjectMapper().readValue(…) so it’s probably the case that performance of > creating new OMs is fine for most users. But I am not talking about slight performance difference here. Creating new ObjectMapper can bring 10x - 100x time taken, depending on platform (latter for Android). And then I get the occasional complaints about poor performance, misleading tests, and claims that library X is 10x faster than Jackson. For what it is worth I do occasionally benchmark "do not reuse ObjectMapper" case with `jmh` test (`jackson-benchmarks`) and difference is 20x for reading. Truly, if it was something like "50% slower" I would not deeply care. But this is something that can not really be optimized on Jackson side (JDK could do a lot wrt caching of generic type information wrt reflection... but I digress). > > * Immutable ObjectMappers would make it _easier_ to re-use existing > objectmappers, because you don’t need to worry that somebody is going to > change the config of your OM. Like I said, I am open some of the approaches. But trying to make ObjectMapper itself immutable, without otherwise changing API is a non-starter for me. But I think we could do something with builder style approach, whereby ObjectMapper would be immutable, and all changes would be accrued via builder(), and new instance obtainer by build(). This would not achieve some of my own ideals (like removing tons of readValue()/writeValue() calls -- although I would prune some of them), but could be workable compromise. -+ Tatu +- > > Jeff > > On Thu, May 11, 2017 at 8:20 AM, Tatu Saloranta <[email protected]> wrote: >> >> On Wed, May 10, 2017 at 12:35 AM, Jeff Schnitzer <[email protected]> >> wrote: >> > I guess what I’m hoping for is something like: >> > >> > final ObjectMapper mapper1 = new >> > ObjectMapper().writeDatesAsTimestamps(false); >> > mapper1.writeValue(stream, thing); >> > final ObjectMapper mapper2 = mapper1.writeDatesAsTimestamps(true); >> > mapper2.writeValue(stream, thing); >> > >> > Of course, if ObjectMapper is immutable then there’s never any need to >> > ’new’ >> > an ObjectMapper. A singleton suffices. >> >> This is how ObjectReader and ObjectWriter work. I think that purely >> from user perspective this approach would makes sense. But from >> implementation perspective there is a reason to keep mapper (or >> whatever you call the factory) separate: it has configurability that >> can not be (easily, cheaply) change on per-call basis (like adding a >> mix-in, or changing aspects of how (de)serializers are constructed). >> This is largely how MapperFeature differs from >> Serialization-/DeserializationFeature: former basically clears all >> cached state and can be incredibly expensive to change. >> >> In addition, unless Builder of some kind is added, number of >> permutations that comes from all configuration aspects gets quite >> unwieldy (for implementing all various "mutant factory" methods). >> Adding a builder could help, but some users would consider this >> further complexity. >> >> -+ Tatu +- >> >> >> > >> > Jeff >> > >> > >> > On Tue, May 9, 2017 at 5:41 PM, Tatu Saloranta <[email protected]> >> > wrote: >> >> >> >> On Mon, May 8, 2017 at 5:00 PM, Jeff Schnitzer <[email protected]> >> >> wrote: >> >> > Is there anything about making ObjectMapper immutable in the works? >> >> > The >> >> > api >> >> > is a bit messy for making new objectmappers derived from old >> >> > objectmappers. >> >> > >> >> > (sorry if this question has already been asked/answered, I’m >> >> > intermittent) >> >> >> >> No, although it would make sense to do one of two things: >> >> >> >> 1. Remove all readValue()/writeValue() calls from ObjectMapper, and >> >> consider it strictly as factory for ObjectReaders and ObjectWriters >> >> 2. Create ObjectMapper builder/factory, which is configurable, but >> >> require construction of immutable mapper for actual use (if so, it'd >> >> be redundant with ObjectReader/ObjectWriter) >> >> >> >> I agree in that at this point ObjectMapper is bit stuck between two >> >> worlds: one where it is to be used directly (original state), and one >> >> where it's merely a factory. >> >> >> >> Division (or not) of reading/writing side is also tricky: >> >> >> >> - On plus side, separating the two simplifies respective APIs and >> >> allows easier identification of which features matter where >> >> - On down side it is more difficult to pass 2 things through >> >> frameworks like JAX-RS or Spring, and they much prefer getting >> >> ObjectMapper >> >> >> >> One thing I have no interest in doing, but that has been proposed, is >> >> adding some kind of flag to indicate that ObjectMapper can not be >> >> configured again: I don't think that approach works well either from >> >> user or implementation perspective. >> >> >> >> -+ Tatu +- >> >> >> >> > >> >> > Jeff >> >> > >> >> > >> >> > >> >> > On Mon, May 8, 2017 at 11:58 AM, Jeff Maxwell >> >> > <[email protected]> >> >> > wrote: >> >> >> >> >> >> Streamify ObjectMapper and ObjectReader >> >> >> >> >> >> ObjectMapper and Object Reader methods that return Iterators should >> >> >> have >> >> >> associated *AsStream methods. >> >> >> >> >> >> Note that users will have to close the returned Streams to avoid >> >> >> leaking >> >> >> resources. >> >> >> >> >> >> Below are potential methods to add: >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(byte[]) >> >> >> DoubleStream readValuesAsDoubleStream(byte[]) >> >> >> IntStream readValuesAsIntStream(byte[]) >> >> >> LongStream readValuesAsLongStream(byte[]) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(byte[], int, int) >> >> >> DoubleStream readValuesAsDoubleStream(byte[], int, int) >> >> >> IntStream readValuesAsIntStream(byte[], int, int) >> >> >> LongStream readValuesAsLongStream(byte[], int, int) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(DataInput) >> >> >> DoubleStream readValuesAsDoubleStream(DataInput) >> >> >> IntStream readValuesAsIntStream(DataInput) >> >> >> LongStream readValuesAsLongStream(DataInput) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(File) >> >> >> DoubleStream readValuesAsDoubleStream(File) >> >> >> IntStream readValuesAsIntStream(File) >> >> >> LongStream readValuesAsLongStream(File) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(InputStream) >> >> >> DoubleStream readValuesAsDoubleStream(InputStream) >> >> >> IntStream readValuesAsIntStream(InputStream) >> >> >> LongStream readValuesAsLongStream(InputStream) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(JsonParser) >> >> >> DoubleStream readValuesAsDoubleStream(JsonParser) >> >> >> IntStream readValuesAsIntStream(JsonParser) >> >> >> LongStream readValuesAsLongStream(JsonParser) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(JsonParser, Class) >> >> >> <T> Stream<T> readValuesAsStream(JsonParser, Class<T>) >> >> >> <T> Stream<T> readValuesAsStream(JsonParser, JavaType) >> >> >> <T> Stream<T> readValuesAsStream(JsonParser, ResolvedType) >> >> >> <T> Stream<T> readValuesAsStream(JsonParser, TypeReference) >> >> >> <T> Stream<T> readValuesAsStream(JsonParser, TypeReference<?>) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(Reader) >> >> >> DoubleStream readValuesAsDoubleStream(Reader) >> >> >> IntStream readValuesAsIntStream(Reader) >> >> >> LongStream readValuesAsLongStream(Reader) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(String) >> >> >> DoubleStream readValuesAsDoubleStream(String) >> >> >> IntStream readValuesAsIntStream(String) >> >> >> LongStream readValuesAsLongStream(String) >> >> >> >> >> >> <T> Stream<T> readValuesAsStream(URL) >> >> >> DoubleStream readValuesAsDoubleStream(URL) >> >> >> IntStream readValuesAsIntStream(URL) >> >> >> LongStream readValuesAsLongStream(URL) >> >> >> >> >> >> >> >> >> >> >> >> On Tuesday, February 21, 2017 at 8:53:03 PM UTC-6, Tatu Saloranta >> >> >> wrote: >> >> >>> >> >> >>> Quick note: I collected existing ideas on my notes to a single wiki >> >> >>> page: >> >> >>> >> >> >>> >> >> >>> >> >> >>> https://github.com/FasterXML/jackson-future-ideas/wiki/Jackson3-Changes >> >> >>> >> >> >>> and intend to evolve that on short term, possibly dividing into >> >> >>> more >> >> >>> granular pages. >> >> >>> Eventually should split those into issues, but before that a lot >> >> >>> more >> >> >>> needs to happen; including question of whether there should be new >> >> >>> repo for Jackson 3 core components. >> >> >>> But I thought it's better to start collecting ideas. >> >> >>> >> >> >>> Another related wiki page is this: >> >> >>> >> >> >>> >> >> >>> >> >> >>> >> >> >>> https://github.com/FasterXML/jackson-future-ideas/wiki/Major-Design-Issues >> >> >>> >> >> >>> and it contains (an incomplete) list of major unsolved issue >> >> >>> regarding >> >> >>> Jackson core design, especially in areas that we have had to >> >> >>> postpone >> >> >>> from 2.9. >> >> >>> >> >> >>> -+ Tatu +- >> >> >> >> >> >> -- >> >> >> You received this message because you are subscribed to the Google >> >> >> Groups >> >> >> "jackson-dev" group. >> >> >> To unsubscribe from this group and stop receiving emails from it, >> >> >> send >> >> >> an >> >> >> email to [email protected]. >> >> >> For more options, visit https://groups.google.com/d/optout. >> >> > >> >> > >> >> > -- >> >> > You received this message because you are subscribed to the Google >> >> > Groups >> >> > "jackson-dev" group. >> >> > To unsubscribe from this group and stop receiving emails from it, >> >> > send >> >> > an >> >> > email to [email protected]. >> >> > For more options, visit https://groups.google.com/d/optout. >> >> >> >> -- >> >> You received this message because you are subscribed to the Google >> >> Groups >> >> "jackson-dev" group. >> >> To unsubscribe from this group and stop receiving emails from it, send >> >> an >> >> email to [email protected]. >> >> For more options, visit https://groups.google.com/d/optout. >> > >> > >> > -- >> > You received this message because you are subscribed to the Google >> > Groups >> > "jackson-dev" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to [email protected]. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- >> You received this message because you are subscribed to the Google Groups >> "jackson-dev" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> For more options, visit https://groups.google.com/d/optout. > > > -- > You received this message because you are subscribed to the Google Groups > "jackson-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "jackson-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
